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