-static int cms_kek_cipher(unsigned char **pout, size_t *poutlen,
- const unsigned char *in, size_t inlen,
- CMS_KeyAgreeRecipientInfo *kari, int enc)
- {
- /* Key encryption key */
- unsigned char kek[EVP_MAX_KEY_LENGTH];
- size_t keklen;
- int rv = 0;
- unsigned char *out = NULL;
- int outlen;
- keklen = EVP_CIPHER_CTX_key_length(&kari->ctx);
- if (keklen > EVP_MAX_KEY_LENGTH)
- return 0;
- /* Derive KEK */
- if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0)
- goto err;
- /* Set KEK in context */
- if (!EVP_CipherInit_ex(&kari->ctx, NULL, NULL, kek, NULL, enc))
- goto err;
- /* obtain output length of ciphered key */
- if (!EVP_CipherUpdate(&kari->ctx, NULL, &outlen, in, inlen))
- goto err;
- out = OPENSSL_malloc(outlen);
- if (!out)
- goto err;
- if (!EVP_CipherUpdate(&kari->ctx, out, &outlen, in, inlen))
- goto err;
- *pout = out;
- *poutlen = (size_t)outlen;
- rv = 1;
-
- err:
- OPENSSL_cleanse(kek, keklen);
- if (!rv && out)
- OPENSSL_free(out);
- EVP_CIPHER_CTX_cleanup(&kari->ctx);
- EVP_PKEY_CTX_free(kari->pctx);
- kari->pctx = NULL;
- return rv;
- }
-
-int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
- CMS_RecipientEncryptedKey *rek)
- {
- int rv = 0;
- unsigned char *enckey = NULL, *cek = NULL;
- size_t enckeylen;
- size_t ceklen;
- CMS_EncryptedContentInfo *ec;
- enckeylen = rek->encryptedKey->length;
- enckey = rek->encryptedKey->data;
- /* Setup all parameters to derive KEK */
- if (!cms_env_asn1_ctrl(ri, 1))
- goto err;
- /* Attempt to decrypt CEK */
- if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0))
- goto err;
- ec = cms->d.envelopedData->encryptedContentInfo;
- if (ec->key)
- {
- OPENSSL_cleanse(ec->key, ec->keylen);
- OPENSSL_free(ec->key);
- }
- ec->key = cek;
- ec->keylen = ceklen;
- cek = NULL;
- rv = 1;
- err:
- if (cek)
- OPENSSL_free(cek);
- return rv;
- }
+static int cms_kek_cipher(unsigned char **pout, size_t *poutlen,
+ const unsigned char *in, size_t inlen,
+ CMS_KeyAgreeRecipientInfo *kari, int enc)
+{
+ /* Key encryption key */
+ unsigned char kek[EVP_MAX_KEY_LENGTH];
+ size_t keklen;
+ int rv = 0;
+ unsigned char *out = NULL;
+ int outlen;
+ keklen = EVP_CIPHER_CTX_key_length(&kari->ctx);
+ if (keklen > EVP_MAX_KEY_LENGTH)
+ return 0;
+ /* Derive KEK */
+ if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0)
+ goto err;
+ /* Set KEK in context */
+ if (!EVP_CipherInit_ex(&kari->ctx, NULL, NULL, kek, NULL, enc))
+ goto err;
+ /* obtain output length of ciphered key */
+ if (!EVP_CipherUpdate(&kari->ctx, NULL, &outlen, in, inlen))
+ goto err;
+ out = OPENSSL_malloc(outlen);
+ if (!out)
+ goto err;
+ if (!EVP_CipherUpdate(&kari->ctx, out, &outlen, in, inlen))
+ goto err;
+ *pout = out;
+ *poutlen = (size_t)outlen;
+ rv = 1;
+
+ err:
+ OPENSSL_cleanse(kek, keklen);
+ if (!rv && out)
+ OPENSSL_free(out);
+ EVP_CIPHER_CTX_cleanup(&kari->ctx);
+ EVP_PKEY_CTX_free(kari->pctx);
+ kari->pctx = NULL;
+ return rv;
+}
+
+int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
+ CMS_RecipientInfo *ri,
+ CMS_RecipientEncryptedKey *rek)
+{
+ int rv = 0;
+ unsigned char *enckey = NULL, *cek = NULL;
+ size_t enckeylen;
+ size_t ceklen;
+ CMS_EncryptedContentInfo *ec;
+ enckeylen = rek->encryptedKey->length;
+ enckey = rek->encryptedKey->data;
+ /* Setup all parameters to derive KEK */
+ if (!cms_env_asn1_ctrl(ri, 1))
+ goto err;
+ /* Attempt to decrypt CEK */
+ if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0))
+ goto err;
+ ec = cms->d.envelopedData->encryptedContentInfo;
+ if (ec->key) {
+ OPENSSL_cleanse(ec->key, ec->keylen);
+ OPENSSL_free(ec->key);
+ }
+ ec->key = cek;
+ ec->keylen = ceklen;
+ cek = NULL;
+ rv = 1;
+ err:
+ if (cek)
+ OPENSSL_free(cek);
+ return rv;
+}