1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * Low level key APIs (DH etc) are deprecated for public use, but still ok for
12e1051a39Sopenharmony_ci * internal use.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#include "internal/deprecated.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
17e1051a39Sopenharmony_ci#include <openssl/asn1t.h>
18e1051a39Sopenharmony_ci#include <openssl/pem.h>
19e1051a39Sopenharmony_ci#include <openssl/x509v3.h>
20e1051a39Sopenharmony_ci#include <openssl/err.h>
21e1051a39Sopenharmony_ci#include <openssl/cms.h>
22e1051a39Sopenharmony_ci#include <openssl/aes.h>
23e1051a39Sopenharmony_ci#include "cms_local.h"
24e1051a39Sopenharmony_ci#include "crypto/asn1.h"
25e1051a39Sopenharmony_ci
26e1051a39Sopenharmony_ci/* Key Agreement Recipient Info (KARI) routines */
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri,
29e1051a39Sopenharmony_ci                                    X509_ALGOR **palg,
30e1051a39Sopenharmony_ci                                    ASN1_OCTET_STRING **pukm)
31e1051a39Sopenharmony_ci{
32e1051a39Sopenharmony_ci    if (ri->type != CMS_RECIPINFO_AGREE) {
33e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
34e1051a39Sopenharmony_ci        return 0;
35e1051a39Sopenharmony_ci    }
36e1051a39Sopenharmony_ci    if (palg)
37e1051a39Sopenharmony_ci        *palg = ri->d.kari->keyEncryptionAlgorithm;
38e1051a39Sopenharmony_ci    if (pukm)
39e1051a39Sopenharmony_ci        *pukm = ri->d.kari->ukm;
40e1051a39Sopenharmony_ci    return 1;
41e1051a39Sopenharmony_ci}
42e1051a39Sopenharmony_ci
43e1051a39Sopenharmony_ci/* Retrieve recipient encrypted keys from a kari */
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_ciSTACK_OF(CMS_RecipientEncryptedKey)
46e1051a39Sopenharmony_ci*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri)
47e1051a39Sopenharmony_ci{
48e1051a39Sopenharmony_ci    if (ri->type != CMS_RECIPINFO_AGREE) {
49e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
50e1051a39Sopenharmony_ci        return NULL;
51e1051a39Sopenharmony_ci    }
52e1051a39Sopenharmony_ci    return ri->d.kari->recipientEncryptedKeys;
53e1051a39Sopenharmony_ci}
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
56e1051a39Sopenharmony_ci                                        X509_ALGOR **pubalg,
57e1051a39Sopenharmony_ci                                        ASN1_BIT_STRING **pubkey,
58e1051a39Sopenharmony_ci                                        ASN1_OCTET_STRING **keyid,
59e1051a39Sopenharmony_ci                                        X509_NAME **issuer,
60e1051a39Sopenharmony_ci                                        ASN1_INTEGER **sno)
61e1051a39Sopenharmony_ci{
62e1051a39Sopenharmony_ci    CMS_OriginatorIdentifierOrKey *oik;
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_ci    if (ri->type != CMS_RECIPINFO_AGREE) {
65e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
66e1051a39Sopenharmony_ci        return 0;
67e1051a39Sopenharmony_ci    }
68e1051a39Sopenharmony_ci    oik = ri->d.kari->originator;
69e1051a39Sopenharmony_ci    if (issuer)
70e1051a39Sopenharmony_ci        *issuer = NULL;
71e1051a39Sopenharmony_ci    if (sno)
72e1051a39Sopenharmony_ci        *sno = NULL;
73e1051a39Sopenharmony_ci    if (keyid)
74e1051a39Sopenharmony_ci        *keyid = NULL;
75e1051a39Sopenharmony_ci    if (pubalg)
76e1051a39Sopenharmony_ci        *pubalg = NULL;
77e1051a39Sopenharmony_ci    if (pubkey)
78e1051a39Sopenharmony_ci        *pubkey = NULL;
79e1051a39Sopenharmony_ci    if (oik->type == CMS_OIK_ISSUER_SERIAL) {
80e1051a39Sopenharmony_ci        if (issuer)
81e1051a39Sopenharmony_ci            *issuer = oik->d.issuerAndSerialNumber->issuer;
82e1051a39Sopenharmony_ci        if (sno)
83e1051a39Sopenharmony_ci            *sno = oik->d.issuerAndSerialNumber->serialNumber;
84e1051a39Sopenharmony_ci    } else if (oik->type == CMS_OIK_KEYIDENTIFIER) {
85e1051a39Sopenharmony_ci        if (keyid)
86e1051a39Sopenharmony_ci            *keyid = oik->d.subjectKeyIdentifier;
87e1051a39Sopenharmony_ci    } else if (oik->type == CMS_OIK_PUBKEY) {
88e1051a39Sopenharmony_ci        if (pubalg)
89e1051a39Sopenharmony_ci            *pubalg = oik->d.originatorKey->algorithm;
90e1051a39Sopenharmony_ci        if (pubkey)
91e1051a39Sopenharmony_ci            *pubkey = oik->d.originatorKey->publicKey;
92e1051a39Sopenharmony_ci    } else
93e1051a39Sopenharmony_ci        return 0;
94e1051a39Sopenharmony_ci    return 1;
95e1051a39Sopenharmony_ci}
96e1051a39Sopenharmony_ci
97e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert)
98e1051a39Sopenharmony_ci{
99e1051a39Sopenharmony_ci    CMS_OriginatorIdentifierOrKey *oik;
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ci    if (ri->type != CMS_RECIPINFO_AGREE) {
102e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
103e1051a39Sopenharmony_ci        return -2;
104e1051a39Sopenharmony_ci    }
105e1051a39Sopenharmony_ci    oik = ri->d.kari->originator;
106e1051a39Sopenharmony_ci    if (oik->type == CMS_OIK_ISSUER_SERIAL)
107e1051a39Sopenharmony_ci        return ossl_cms_ias_cert_cmp(oik->d.issuerAndSerialNumber, cert);
108e1051a39Sopenharmony_ci    else if (oik->type == CMS_OIK_KEYIDENTIFIER)
109e1051a39Sopenharmony_ci        return ossl_cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert);
110e1051a39Sopenharmony_ci    return -1;
111e1051a39Sopenharmony_ci}
112e1051a39Sopenharmony_ci
113e1051a39Sopenharmony_ciint CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
114e1051a39Sopenharmony_ci                                      ASN1_OCTET_STRING **keyid,
115e1051a39Sopenharmony_ci                                      ASN1_GENERALIZEDTIME **tm,
116e1051a39Sopenharmony_ci                                      CMS_OtherKeyAttribute **other,
117e1051a39Sopenharmony_ci                                      X509_NAME **issuer, ASN1_INTEGER **sno)
118e1051a39Sopenharmony_ci{
119e1051a39Sopenharmony_ci    CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
120e1051a39Sopenharmony_ci
121e1051a39Sopenharmony_ci    if (rid->type == CMS_REK_ISSUER_SERIAL) {
122e1051a39Sopenharmony_ci        if (issuer)
123e1051a39Sopenharmony_ci            *issuer = rid->d.issuerAndSerialNumber->issuer;
124e1051a39Sopenharmony_ci        if (sno)
125e1051a39Sopenharmony_ci            *sno = rid->d.issuerAndSerialNumber->serialNumber;
126e1051a39Sopenharmony_ci        if (keyid)
127e1051a39Sopenharmony_ci            *keyid = NULL;
128e1051a39Sopenharmony_ci        if (tm)
129e1051a39Sopenharmony_ci            *tm = NULL;
130e1051a39Sopenharmony_ci        if (other)
131e1051a39Sopenharmony_ci            *other = NULL;
132e1051a39Sopenharmony_ci    } else if (rid->type == CMS_REK_KEYIDENTIFIER) {
133e1051a39Sopenharmony_ci        if (keyid)
134e1051a39Sopenharmony_ci            *keyid = rid->d.rKeyId->subjectKeyIdentifier;
135e1051a39Sopenharmony_ci        if (tm)
136e1051a39Sopenharmony_ci            *tm = rid->d.rKeyId->date;
137e1051a39Sopenharmony_ci        if (other)
138e1051a39Sopenharmony_ci            *other = rid->d.rKeyId->other;
139e1051a39Sopenharmony_ci        if (issuer)
140e1051a39Sopenharmony_ci            *issuer = NULL;
141e1051a39Sopenharmony_ci        if (sno)
142e1051a39Sopenharmony_ci            *sno = NULL;
143e1051a39Sopenharmony_ci    } else
144e1051a39Sopenharmony_ci        return 0;
145e1051a39Sopenharmony_ci    return 1;
146e1051a39Sopenharmony_ci}
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_ciint CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
149e1051a39Sopenharmony_ci                                       X509 *cert)
150e1051a39Sopenharmony_ci{
151e1051a39Sopenharmony_ci    CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
152e1051a39Sopenharmony_ci
153e1051a39Sopenharmony_ci    if (rid->type == CMS_REK_ISSUER_SERIAL)
154e1051a39Sopenharmony_ci        return ossl_cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert);
155e1051a39Sopenharmony_ci    else if (rid->type == CMS_REK_KEYIDENTIFIER)
156e1051a39Sopenharmony_ci        return ossl_cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier,
157e1051a39Sopenharmony_ci                                       cert);
158e1051a39Sopenharmony_ci    else
159e1051a39Sopenharmony_ci        return -1;
160e1051a39Sopenharmony_ci}
161e1051a39Sopenharmony_ci
162e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri,
163e1051a39Sopenharmony_ci                                              EVP_PKEY *pk, X509 *peer)
164e1051a39Sopenharmony_ci{
165e1051a39Sopenharmony_ci    EVP_PKEY_CTX *pctx;
166e1051a39Sopenharmony_ci    CMS_KeyAgreeRecipientInfo *kari = ri->d.kari;
167e1051a39Sopenharmony_ci
168e1051a39Sopenharmony_ci    EVP_PKEY_CTX_free(kari->pctx);
169e1051a39Sopenharmony_ci    kari->pctx = NULL;
170e1051a39Sopenharmony_ci    if (pk == NULL)
171e1051a39Sopenharmony_ci        return 1;
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ci    pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(kari->cms_ctx),
174e1051a39Sopenharmony_ci                                      pk,
175e1051a39Sopenharmony_ci                                      ossl_cms_ctx_get0_propq(kari->cms_ctx));
176e1051a39Sopenharmony_ci    if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0)
177e1051a39Sopenharmony_ci        goto err;
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_ci    if (peer != NULL) {
180e1051a39Sopenharmony_ci        EVP_PKEY *pub_pkey = X509_get0_pubkey(peer);
181e1051a39Sopenharmony_ci
182e1051a39Sopenharmony_ci        if (EVP_PKEY_derive_set_peer(pctx, pub_pkey) <= 0)
183e1051a39Sopenharmony_ci            goto err;
184e1051a39Sopenharmony_ci    }
185e1051a39Sopenharmony_ci
186e1051a39Sopenharmony_ci    kari->pctx = pctx;
187e1051a39Sopenharmony_ci    return 1;
188e1051a39Sopenharmony_ci err:
189e1051a39Sopenharmony_ci    EVP_PKEY_CTX_free(pctx);
190e1051a39Sopenharmony_ci    return 0;
191e1051a39Sopenharmony_ci}
192e1051a39Sopenharmony_ci
193e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
194e1051a39Sopenharmony_ci{
195e1051a39Sopenharmony_ci    return CMS_RecipientInfo_kari_set0_pkey_and_peer(ri, pk, NULL);
196e1051a39Sopenharmony_ci}
197e1051a39Sopenharmony_ci
198e1051a39Sopenharmony_ciEVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri)
199e1051a39Sopenharmony_ci{
200e1051a39Sopenharmony_ci    if (ri->type == CMS_RECIPINFO_AGREE)
201e1051a39Sopenharmony_ci        return ri->d.kari->ctx;
202e1051a39Sopenharmony_ci    return NULL;
203e1051a39Sopenharmony_ci}
204e1051a39Sopenharmony_ci
205e1051a39Sopenharmony_ci/*
206e1051a39Sopenharmony_ci * Derive KEK and decrypt/encrypt with it to produce either the original CEK
207e1051a39Sopenharmony_ci * or the encrypted CEK.
208e1051a39Sopenharmony_ci */
209e1051a39Sopenharmony_ci
210e1051a39Sopenharmony_cistatic int cms_kek_cipher(unsigned char **pout, size_t *poutlen,
211e1051a39Sopenharmony_ci                          const unsigned char *in, size_t inlen,
212e1051a39Sopenharmony_ci                          CMS_KeyAgreeRecipientInfo *kari, int enc)
213e1051a39Sopenharmony_ci{
214e1051a39Sopenharmony_ci    /* Key encryption key */
215e1051a39Sopenharmony_ci    unsigned char kek[EVP_MAX_KEY_LENGTH];
216e1051a39Sopenharmony_ci    size_t keklen;
217e1051a39Sopenharmony_ci    int rv = 0;
218e1051a39Sopenharmony_ci    unsigned char *out = NULL;
219e1051a39Sopenharmony_ci    int outlen;
220e1051a39Sopenharmony_ci
221e1051a39Sopenharmony_ci    keklen = EVP_CIPHER_CTX_get_key_length(kari->ctx);
222e1051a39Sopenharmony_ci    if (keklen > EVP_MAX_KEY_LENGTH)
223e1051a39Sopenharmony_ci        return 0;
224e1051a39Sopenharmony_ci    /* Derive KEK */
225e1051a39Sopenharmony_ci    if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0)
226e1051a39Sopenharmony_ci        goto err;
227e1051a39Sopenharmony_ci    /* Set KEK in context */
228e1051a39Sopenharmony_ci    if (!EVP_CipherInit_ex(kari->ctx, NULL, NULL, kek, NULL, enc))
229e1051a39Sopenharmony_ci        goto err;
230e1051a39Sopenharmony_ci    /* obtain output length of ciphered key */
231e1051a39Sopenharmony_ci    if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen))
232e1051a39Sopenharmony_ci        goto err;
233e1051a39Sopenharmony_ci    out = OPENSSL_malloc(outlen);
234e1051a39Sopenharmony_ci    if (out == NULL)
235e1051a39Sopenharmony_ci        goto err;
236e1051a39Sopenharmony_ci    if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen))
237e1051a39Sopenharmony_ci        goto err;
238e1051a39Sopenharmony_ci    *pout = out;
239e1051a39Sopenharmony_ci    *poutlen = (size_t)outlen;
240e1051a39Sopenharmony_ci    rv = 1;
241e1051a39Sopenharmony_ci
242e1051a39Sopenharmony_ci err:
243e1051a39Sopenharmony_ci    OPENSSL_cleanse(kek, keklen);
244e1051a39Sopenharmony_ci    if (!rv)
245e1051a39Sopenharmony_ci        OPENSSL_free(out);
246e1051a39Sopenharmony_ci    EVP_CIPHER_CTX_reset(kari->ctx);
247e1051a39Sopenharmony_ci    /* FIXME: WHY IS kari->pctx freed here?  /RL */
248e1051a39Sopenharmony_ci    EVP_PKEY_CTX_free(kari->pctx);
249e1051a39Sopenharmony_ci    kari->pctx = NULL;
250e1051a39Sopenharmony_ci    return rv;
251e1051a39Sopenharmony_ci}
252e1051a39Sopenharmony_ci
253e1051a39Sopenharmony_ciint CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
254e1051a39Sopenharmony_ci                                   CMS_RecipientInfo *ri,
255e1051a39Sopenharmony_ci                                   CMS_RecipientEncryptedKey *rek)
256e1051a39Sopenharmony_ci{
257e1051a39Sopenharmony_ci    int rv = 0;
258e1051a39Sopenharmony_ci    unsigned char *enckey = NULL, *cek = NULL;
259e1051a39Sopenharmony_ci    size_t enckeylen;
260e1051a39Sopenharmony_ci    size_t ceklen;
261e1051a39Sopenharmony_ci    CMS_EncryptedContentInfo *ec;
262e1051a39Sopenharmony_ci
263e1051a39Sopenharmony_ci    enckeylen = rek->encryptedKey->length;
264e1051a39Sopenharmony_ci    enckey = rek->encryptedKey->data;
265e1051a39Sopenharmony_ci    /* Setup all parameters to derive KEK */
266e1051a39Sopenharmony_ci    if (!ossl_cms_env_asn1_ctrl(ri, 1))
267e1051a39Sopenharmony_ci        goto err;
268e1051a39Sopenharmony_ci    /* Attempt to decrypt CEK */
269e1051a39Sopenharmony_ci    if (!cms_kek_cipher(&cek, &ceklen, enckey, enckeylen, ri->d.kari, 0))
270e1051a39Sopenharmony_ci        goto err;
271e1051a39Sopenharmony_ci    ec = ossl_cms_get0_env_enc_content(cms);
272e1051a39Sopenharmony_ci    OPENSSL_clear_free(ec->key, ec->keylen);
273e1051a39Sopenharmony_ci    ec->key = cek;
274e1051a39Sopenharmony_ci    ec->keylen = ceklen;
275e1051a39Sopenharmony_ci    cek = NULL;
276e1051a39Sopenharmony_ci    rv = 1;
277e1051a39Sopenharmony_ci err:
278e1051a39Sopenharmony_ci    OPENSSL_free(cek);
279e1051a39Sopenharmony_ci    return rv;
280e1051a39Sopenharmony_ci}
281e1051a39Sopenharmony_ci
282e1051a39Sopenharmony_ci/* Create ephemeral key and initialise context based on it */
283e1051a39Sopenharmony_cistatic int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
284e1051a39Sopenharmony_ci                                         EVP_PKEY *pk)
285e1051a39Sopenharmony_ci{
286e1051a39Sopenharmony_ci    EVP_PKEY_CTX *pctx = NULL;
287e1051a39Sopenharmony_ci    EVP_PKEY *ekey = NULL;
288e1051a39Sopenharmony_ci    int rv = 0;
289e1051a39Sopenharmony_ci    const CMS_CTX *ctx = kari->cms_ctx;
290e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
291e1051a39Sopenharmony_ci    const char *propq = ossl_cms_ctx_get0_propq(ctx);
292e1051a39Sopenharmony_ci
293e1051a39Sopenharmony_ci    pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propq);
294e1051a39Sopenharmony_ci    if (pctx == NULL)
295e1051a39Sopenharmony_ci        goto err;
296e1051a39Sopenharmony_ci    if (EVP_PKEY_keygen_init(pctx) <= 0)
297e1051a39Sopenharmony_ci        goto err;
298e1051a39Sopenharmony_ci    if (EVP_PKEY_keygen(pctx, &ekey) <= 0)
299e1051a39Sopenharmony_ci        goto err;
300e1051a39Sopenharmony_ci    EVP_PKEY_CTX_free(pctx);
301e1051a39Sopenharmony_ci    pctx = EVP_PKEY_CTX_new_from_pkey(libctx, ekey, propq);
302e1051a39Sopenharmony_ci    if (pctx == NULL)
303e1051a39Sopenharmony_ci        goto err;
304e1051a39Sopenharmony_ci    if (EVP_PKEY_derive_init(pctx) <= 0)
305e1051a39Sopenharmony_ci        goto err;
306e1051a39Sopenharmony_ci    kari->pctx = pctx;
307e1051a39Sopenharmony_ci    rv = 1;
308e1051a39Sopenharmony_ci err:
309e1051a39Sopenharmony_ci    if (!rv)
310e1051a39Sopenharmony_ci        EVP_PKEY_CTX_free(pctx);
311e1051a39Sopenharmony_ci    EVP_PKEY_free(ekey);
312e1051a39Sopenharmony_ci    return rv;
313e1051a39Sopenharmony_ci}
314e1051a39Sopenharmony_ci
315e1051a39Sopenharmony_ci/* Set originator private key and initialise context based on it */
316e1051a39Sopenharmony_cistatic int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari,
317e1051a39Sopenharmony_ci                                               EVP_PKEY *originatorPrivKey )
318e1051a39Sopenharmony_ci{
319e1051a39Sopenharmony_ci    EVP_PKEY_CTX *pctx = NULL;
320e1051a39Sopenharmony_ci    int rv = 0;
321e1051a39Sopenharmony_ci    const CMS_CTX *ctx = kari->cms_ctx;
322e1051a39Sopenharmony_ci
323e1051a39Sopenharmony_ci    pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
324e1051a39Sopenharmony_ci                                      originatorPrivKey,
325e1051a39Sopenharmony_ci                                      ossl_cms_ctx_get0_propq(ctx));
326e1051a39Sopenharmony_ci    if (pctx == NULL)
327e1051a39Sopenharmony_ci        goto err;
328e1051a39Sopenharmony_ci    if (EVP_PKEY_derive_init(pctx) <= 0)
329e1051a39Sopenharmony_ci         goto err;
330e1051a39Sopenharmony_ci
331e1051a39Sopenharmony_ci    kari->pctx = pctx;
332e1051a39Sopenharmony_ci    rv = 1;
333e1051a39Sopenharmony_ci err:
334e1051a39Sopenharmony_ci    if (rv == 0)
335e1051a39Sopenharmony_ci        EVP_PKEY_CTX_free(pctx);
336e1051a39Sopenharmony_ci    return rv;
337e1051a39Sopenharmony_ci}
338e1051a39Sopenharmony_ci
339e1051a39Sopenharmony_ci/* Initialise a kari based on passed certificate and key */
340e1051a39Sopenharmony_ci
341e1051a39Sopenharmony_ciint ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri,  X509 *recip,
342e1051a39Sopenharmony_ci                                     EVP_PKEY *recipPubKey, X509 *originator,
343e1051a39Sopenharmony_ci                                     EVP_PKEY *originatorPrivKey,
344e1051a39Sopenharmony_ci                                     unsigned int flags, const CMS_CTX *ctx)
345e1051a39Sopenharmony_ci{
346e1051a39Sopenharmony_ci    CMS_KeyAgreeRecipientInfo *kari;
347e1051a39Sopenharmony_ci    CMS_RecipientEncryptedKey *rek = NULL;
348e1051a39Sopenharmony_ci
349e1051a39Sopenharmony_ci    ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo);
350e1051a39Sopenharmony_ci    if (ri->d.kari == NULL)
351e1051a39Sopenharmony_ci        return 0;
352e1051a39Sopenharmony_ci    ri->type = CMS_RECIPINFO_AGREE;
353e1051a39Sopenharmony_ci
354e1051a39Sopenharmony_ci    kari = ri->d.kari;
355e1051a39Sopenharmony_ci    kari->version = 3;
356e1051a39Sopenharmony_ci    kari->cms_ctx = ctx;
357e1051a39Sopenharmony_ci
358e1051a39Sopenharmony_ci    rek = M_ASN1_new_of(CMS_RecipientEncryptedKey);
359e1051a39Sopenharmony_ci    if (rek == NULL)
360e1051a39Sopenharmony_ci        return 0;
361e1051a39Sopenharmony_ci
362e1051a39Sopenharmony_ci    if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) {
363e1051a39Sopenharmony_ci        M_ASN1_free_of(rek, CMS_RecipientEncryptedKey);
364e1051a39Sopenharmony_ci        return 0;
365e1051a39Sopenharmony_ci    }
366e1051a39Sopenharmony_ci
367e1051a39Sopenharmony_ci    if (flags & CMS_USE_KEYID) {
368e1051a39Sopenharmony_ci        rek->rid->type = CMS_REK_KEYIDENTIFIER;
369e1051a39Sopenharmony_ci        rek->rid->d.rKeyId = M_ASN1_new_of(CMS_RecipientKeyIdentifier);
370e1051a39Sopenharmony_ci        if (rek->rid->d.rKeyId == NULL)
371e1051a39Sopenharmony_ci            return 0;
372e1051a39Sopenharmony_ci        if (!ossl_cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip))
373e1051a39Sopenharmony_ci            return 0;
374e1051a39Sopenharmony_ci    } else {
375e1051a39Sopenharmony_ci        rek->rid->type = CMS_REK_ISSUER_SERIAL;
376e1051a39Sopenharmony_ci        if (!ossl_cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip))
377e1051a39Sopenharmony_ci            return 0;
378e1051a39Sopenharmony_ci    }
379e1051a39Sopenharmony_ci
380e1051a39Sopenharmony_ci    if (originatorPrivKey == NULL && originator == NULL) {
381e1051a39Sopenharmony_ci        /* Create ephemeral key */
382e1051a39Sopenharmony_ci        if (!cms_kari_create_ephemeral_key(kari, recipPubKey))
383e1051a39Sopenharmony_ci            return 0;
384e1051a39Sopenharmony_ci    } else {
385e1051a39Sopenharmony_ci        /* Use originator key */
386e1051a39Sopenharmony_ci        CMS_OriginatorIdentifierOrKey *oik = ri->d.kari->originator;
387e1051a39Sopenharmony_ci
388e1051a39Sopenharmony_ci        if (originatorPrivKey == NULL || originator == NULL)
389e1051a39Sopenharmony_ci            return 0;
390e1051a39Sopenharmony_ci
391e1051a39Sopenharmony_ci        if (flags & CMS_USE_ORIGINATOR_KEYID) {
392e1051a39Sopenharmony_ci             oik->type = CMS_OIK_KEYIDENTIFIER;
393e1051a39Sopenharmony_ci             oik->d.subjectKeyIdentifier = ASN1_OCTET_STRING_new();
394e1051a39Sopenharmony_ci             if (oik->d.subjectKeyIdentifier == NULL)
395e1051a39Sopenharmony_ci                  return 0;
396e1051a39Sopenharmony_ci             if (!ossl_cms_set1_keyid(&oik->d.subjectKeyIdentifier, originator))
397e1051a39Sopenharmony_ci                  return 0;
398e1051a39Sopenharmony_ci        } else {
399e1051a39Sopenharmony_ci             oik->type = CMS_REK_ISSUER_SERIAL;
400e1051a39Sopenharmony_ci             if (!ossl_cms_set1_ias(&oik->d.issuerAndSerialNumber, originator))
401e1051a39Sopenharmony_ci                  return 0;
402e1051a39Sopenharmony_ci        }
403e1051a39Sopenharmony_ci
404e1051a39Sopenharmony_ci        if (!cms_kari_set_originator_private_key(kari, originatorPrivKey))
405e1051a39Sopenharmony_ci            return 0;
406e1051a39Sopenharmony_ci    }
407e1051a39Sopenharmony_ci
408e1051a39Sopenharmony_ci    EVP_PKEY_up_ref(recipPubKey);
409e1051a39Sopenharmony_ci    rek->pkey = recipPubKey;
410e1051a39Sopenharmony_ci    return 1;
411e1051a39Sopenharmony_ci}
412e1051a39Sopenharmony_ci
413e1051a39Sopenharmony_cistatic int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
414e1051a39Sopenharmony_ci                         const EVP_CIPHER *cipher)
415e1051a39Sopenharmony_ci{
416e1051a39Sopenharmony_ci    const CMS_CTX *cms_ctx = kari->cms_ctx;
417e1051a39Sopenharmony_ci    EVP_CIPHER_CTX *ctx = kari->ctx;
418e1051a39Sopenharmony_ci    const EVP_CIPHER *kekcipher;
419e1051a39Sopenharmony_ci    EVP_CIPHER *fetched_kekcipher;
420e1051a39Sopenharmony_ci    const char *kekcipher_name;
421e1051a39Sopenharmony_ci    int keylen;
422e1051a39Sopenharmony_ci    int ret;
423e1051a39Sopenharmony_ci
424e1051a39Sopenharmony_ci    /* If a suitable wrap algorithm is already set nothing to do */
425e1051a39Sopenharmony_ci    kekcipher = EVP_CIPHER_CTX_get0_cipher(ctx);
426e1051a39Sopenharmony_ci    if (kekcipher != NULL) {
427e1051a39Sopenharmony_ci        if (EVP_CIPHER_CTX_get_mode(ctx) != EVP_CIPH_WRAP_MODE)
428e1051a39Sopenharmony_ci            return 0;
429e1051a39Sopenharmony_ci        return 1;
430e1051a39Sopenharmony_ci    }
431e1051a39Sopenharmony_ci    if (cipher == NULL)
432e1051a39Sopenharmony_ci        return 0;
433e1051a39Sopenharmony_ci    keylen = EVP_CIPHER_get_key_length(cipher);
434e1051a39Sopenharmony_ci    if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_GET_WRAP_CIPHER) != 0) {
435e1051a39Sopenharmony_ci        ret = EVP_CIPHER_meth_get_ctrl(cipher)(NULL, EVP_CTRL_GET_WRAP_CIPHER,
436e1051a39Sopenharmony_ci                                               0, &kekcipher);
437e1051a39Sopenharmony_ci        if (ret <= 0)
438e1051a39Sopenharmony_ci             return 0;
439e1051a39Sopenharmony_ci
440e1051a39Sopenharmony_ci        if (kekcipher != NULL) {
441e1051a39Sopenharmony_ci             if (EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
442e1051a39Sopenharmony_ci                 return 0;
443e1051a39Sopenharmony_ci             kekcipher_name = EVP_CIPHER_get0_name(kekcipher);
444e1051a39Sopenharmony_ci             goto enc;
445e1051a39Sopenharmony_ci        }
446e1051a39Sopenharmony_ci    }
447e1051a39Sopenharmony_ci
448e1051a39Sopenharmony_ci    /*
449e1051a39Sopenharmony_ci     * Pick a cipher based on content encryption cipher. If it is DES3 use
450e1051a39Sopenharmony_ci     * DES3 wrap otherwise use AES wrap similar to key size.
451e1051a39Sopenharmony_ci     */
452e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DES
453e1051a39Sopenharmony_ci    if (EVP_CIPHER_get_type(cipher) == NID_des_ede3_cbc)
454e1051a39Sopenharmony_ci        kekcipher_name = SN_id_smime_alg_CMS3DESwrap;
455e1051a39Sopenharmony_ci    else
456e1051a39Sopenharmony_ci#endif
457e1051a39Sopenharmony_ci    if (keylen <= 16)
458e1051a39Sopenharmony_ci        kekcipher_name = SN_id_aes128_wrap;
459e1051a39Sopenharmony_ci    else if (keylen <= 24)
460e1051a39Sopenharmony_ci        kekcipher_name = SN_id_aes192_wrap;
461e1051a39Sopenharmony_ci    else
462e1051a39Sopenharmony_ci        kekcipher_name = SN_id_aes256_wrap;
463e1051a39Sopenharmony_cienc:
464e1051a39Sopenharmony_ci    fetched_kekcipher = EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(cms_ctx),
465e1051a39Sopenharmony_ci                                         kekcipher_name,
466e1051a39Sopenharmony_ci                                         ossl_cms_ctx_get0_propq(cms_ctx));
467e1051a39Sopenharmony_ci    if (fetched_kekcipher == NULL)
468e1051a39Sopenharmony_ci        return 0;
469e1051a39Sopenharmony_ci    ret = EVP_EncryptInit_ex(ctx, fetched_kekcipher, NULL, NULL, NULL);
470e1051a39Sopenharmony_ci    EVP_CIPHER_free(fetched_kekcipher);
471e1051a39Sopenharmony_ci    return ret;
472e1051a39Sopenharmony_ci}
473e1051a39Sopenharmony_ci
474e1051a39Sopenharmony_ci/* Encrypt content key in key agreement recipient info */
475e1051a39Sopenharmony_ci
476e1051a39Sopenharmony_ciint ossl_cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
477e1051a39Sopenharmony_ci                                        CMS_RecipientInfo *ri)
478e1051a39Sopenharmony_ci{
479e1051a39Sopenharmony_ci    CMS_KeyAgreeRecipientInfo *kari;
480e1051a39Sopenharmony_ci    CMS_EncryptedContentInfo *ec;
481e1051a39Sopenharmony_ci    CMS_RecipientEncryptedKey *rek;
482e1051a39Sopenharmony_ci    STACK_OF(CMS_RecipientEncryptedKey) *reks;
483e1051a39Sopenharmony_ci    int i;
484e1051a39Sopenharmony_ci
485e1051a39Sopenharmony_ci    if (ri->type != CMS_RECIPINFO_AGREE) {
486e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_AGREEMENT);
487e1051a39Sopenharmony_ci        return 0;
488e1051a39Sopenharmony_ci    }
489e1051a39Sopenharmony_ci    kari = ri->d.kari;
490e1051a39Sopenharmony_ci    reks = kari->recipientEncryptedKeys;
491e1051a39Sopenharmony_ci    ec = ossl_cms_get0_env_enc_content(cms);
492e1051a39Sopenharmony_ci    /* Initialise wrap algorithm parameters */
493e1051a39Sopenharmony_ci    if (!cms_wrap_init(kari, ec->cipher))
494e1051a39Sopenharmony_ci        return 0;
495e1051a39Sopenharmony_ci    /*
496e1051a39Sopenharmony_ci     * If no originator key set up initialise for ephemeral key the public key
497e1051a39Sopenharmony_ci     * ASN1 structure will set the actual public key value.
498e1051a39Sopenharmony_ci     */
499e1051a39Sopenharmony_ci    if (kari->originator->type == -1) {
500e1051a39Sopenharmony_ci        CMS_OriginatorIdentifierOrKey *oik = kari->originator;
501e1051a39Sopenharmony_ci        oik->type = CMS_OIK_PUBKEY;
502e1051a39Sopenharmony_ci        oik->d.originatorKey = M_ASN1_new_of(CMS_OriginatorPublicKey);
503e1051a39Sopenharmony_ci        if (!oik->d.originatorKey)
504e1051a39Sopenharmony_ci            return 0;
505e1051a39Sopenharmony_ci    }
506e1051a39Sopenharmony_ci    /* Initialise KDF algorithm */
507e1051a39Sopenharmony_ci    if (!ossl_cms_env_asn1_ctrl(ri, 0))
508e1051a39Sopenharmony_ci        return 0;
509e1051a39Sopenharmony_ci    /* For each rek, derive KEK, encrypt CEK */
510e1051a39Sopenharmony_ci    for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
511e1051a39Sopenharmony_ci        unsigned char *enckey;
512e1051a39Sopenharmony_ci        size_t enckeylen;
513e1051a39Sopenharmony_ci        rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
514e1051a39Sopenharmony_ci        if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0)
515e1051a39Sopenharmony_ci            return 0;
516e1051a39Sopenharmony_ci        if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen,
517e1051a39Sopenharmony_ci                            kari, 1))
518e1051a39Sopenharmony_ci            return 0;
519e1051a39Sopenharmony_ci        ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen);
520e1051a39Sopenharmony_ci    }
521e1051a39Sopenharmony_ci
522e1051a39Sopenharmony_ci    return 1;
523e1051a39Sopenharmony_ci}
524