1 /*
2  * Copyright 2009-2025 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 #include "internal/cryptlib.h"
11 #include <openssl/asn1t.h>
12 #include <openssl/pem.h>
13 #include <openssl/x509v3.h>
14 #include <openssl/err.h>
15 #include <openssl/cms.h>
16 #include <openssl/rand.h>
17 #include <openssl/aes.h>
18 #include "internal/sizes.h"
19 #include "crypto/asn1.h"
20 #include "cms_local.h"
21 
CMS_RecipientInfo_set0_password(CMS_RecipientInfo * ri,unsigned char * pass,ossl_ssize_t passlen)22 int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri,
23                                     unsigned char *pass, ossl_ssize_t passlen)
24 {
25     CMS_PasswordRecipientInfo *pwri;
26     if (ri->type != CMS_RECIPINFO_PASS) {
27         ERR_raise(ERR_LIB_CMS, CMS_R_NOT_PWRI);
28         return 0;
29     }
30 
31     pwri = ri->d.pwri;
32     pwri->pass = pass;
33     if (pass && passlen < 0)
34         passlen = strlen((char *)pass);
35     pwri->passlen = passlen;
36     return 1;
37 }
38 
CMS_add0_recipient_password(CMS_ContentInfo * cms,int iter,int wrap_nid,int pbe_nid,unsigned char * pass,ossl_ssize_t passlen,const EVP_CIPHER * kekciph)39 CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
40                                                int iter, int wrap_nid,
41                                                int pbe_nid,
42                                                unsigned char *pass,
43                                                ossl_ssize_t passlen,
44                                                const EVP_CIPHER *kekciph)
45 {
46     STACK_OF(CMS_RecipientInfo) *ris;
47     CMS_RecipientInfo *ri = NULL;
48     CMS_EncryptedContentInfo *ec;
49     CMS_PasswordRecipientInfo *pwri;
50     EVP_CIPHER_CTX *ctx = NULL;
51     X509_ALGOR *encalg = NULL;
52     unsigned char iv[EVP_MAX_IV_LENGTH];
53     int ivlen;
54     const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms);
55 
56     ec = ossl_cms_get0_env_enc_content(cms);
57     if (ec == NULL)
58         return NULL;
59     ris = CMS_get0_RecipientInfos(cms);
60     if (ris == NULL)
61         return NULL;
62 
63     if (wrap_nid <= 0)
64         wrap_nid = NID_id_alg_PWRI_KEK;
65 
66     /* Get from enveloped data */
67     if (kekciph == NULL)
68         kekciph = ec->cipher;
69 
70     if (kekciph == NULL) {
71         ERR_raise(ERR_LIB_CMS, CMS_R_NO_CIPHER);
72         return NULL;
73     }
74     if ((EVP_CIPHER_get_flags(kekciph) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) {
75         ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEK_ALGORITHM);
76         return NULL;
77     }
78     if (wrap_nid != NID_id_alg_PWRI_KEK) {
79         ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
80         return NULL;
81     }
82 
83     /* Setup algorithm identifier for cipher */
84     encalg = X509_ALGOR_new();
85     if (encalg == NULL) {
86         ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
87         goto err;
88     }
89     ctx = EVP_CIPHER_CTX_new();
90     if (ctx == NULL) {
91         ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
92         goto err;
93     }
94 
95     if (EVP_EncryptInit_ex(ctx, kekciph, NULL, NULL, NULL) <= 0) {
96         ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
97         goto err;
98     }
99 
100     ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
101     if (ivlen < 0) {
102         ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
103         goto err;
104     }
105 
106     if (ivlen > 0) {
107         if (RAND_bytes_ex(ossl_cms_ctx_get0_libctx(cms_ctx), iv, ivlen, 0) <= 0)
108             goto err;
109         if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) <= 0) {
110             ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
111             goto err;
112         }
113         encalg->parameter = ASN1_TYPE_new();
114         if (!encalg->parameter) {
115             ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
116             goto err;
117         }
118         if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) {
119             ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
120             goto err;
121         }
122     }
123 
124     encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_get_type(ctx));
125 
126     EVP_CIPHER_CTX_free(ctx);
127     ctx = NULL;
128 
129     /* Initialize recipient info */
130     ri = M_ASN1_new_of(CMS_RecipientInfo);
131     if (ri == NULL) {
132         ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
133         goto err;
134     }
135 
136     ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo);
137     if (ri->d.pwri == NULL) {
138         ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
139         goto err;
140     }
141     ri->encoded_type = ri->type = CMS_RECIPINFO_PASS;
142 
143     pwri = ri->d.pwri;
144     pwri->cms_ctx = cms_ctx;
145     /* Since this is overwritten, free up empty structure already there */
146     X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
147     pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
148     if (pwri->keyEncryptionAlgorithm == NULL) {
149         ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
150         goto err;
151     }
152     pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid);
153     pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new();
154     if (pwri->keyEncryptionAlgorithm->parameter == NULL) {
155         ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
156         goto err;
157     }
158 
159     if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR),
160                         &pwri->keyEncryptionAlgorithm->parameter->
161                         value.sequence)) {
162         ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB);
163         goto err;
164     }
165     pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE;
166 
167     X509_ALGOR_free(encalg);
168     encalg = NULL;
169 
170     /* Setup PBE algorithm */
171 
172     pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set_ex(iter, NULL, 0, -1, -1,
173                                                        cms_ctx->libctx);
174 
175     if (pwri->keyDerivationAlgorithm == NULL)
176         goto err;
177 
178     CMS_RecipientInfo_set0_password(ri, pass, passlen);
179     pwri->version = 0;
180 
181     if (!sk_CMS_RecipientInfo_push(ris, ri)) {
182         ERR_raise(ERR_LIB_CMS, ERR_R_CRYPTO_LIB);
183         goto err;
184     }
185 
186     return ri;
187 
188  err:
189     EVP_CIPHER_CTX_free(ctx);
190     if (ri)
191         M_ASN1_free_of(ri, CMS_RecipientInfo);
192     X509_ALGOR_free(encalg);
193     return NULL;
194 
195 }
196 
197 /*
198  * This is an implementation of the key wrapping mechanism in RFC3211, at
199  * some point this should go into EVP.
200  */
201 
kek_unwrap_key(unsigned char * out,size_t * outlen,const unsigned char * in,size_t inlen,EVP_CIPHER_CTX * ctx)202 static int kek_unwrap_key(unsigned char *out, size_t *outlen,
203                           const unsigned char *in, size_t inlen,
204                           EVP_CIPHER_CTX *ctx)
205 {
206     int blocklen = EVP_CIPHER_CTX_get_block_size(ctx);
207     unsigned char *tmp;
208     int outl, rv = 0;
209 
210     if (blocklen <= 0)
211         return 0;
212 
213     if (inlen < 2 * (size_t)blocklen) {
214         /* too small */
215         return 0;
216     }
217     if (inlen > INT_MAX || inlen % blocklen) {
218         /* Invalid size */
219         return 0;
220     }
221     if ((tmp = OPENSSL_malloc(inlen)) == NULL)
222         return 0;
223     /* setup IV by decrypting last two blocks */
224     if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl,
225                            in + inlen - 2 * blocklen, blocklen * 2)
226         /*
227          * Do a decrypt of last decrypted block to set IV to correct value
228          * output it to start of buffer so we don't corrupt decrypted block
229          * this works because buffer is at least two block lengths long.
230          */
231         || !EVP_DecryptUpdate(ctx, tmp, &outl,
232                               tmp + inlen - blocklen, blocklen)
233         /* Can now decrypt first n - 1 blocks */
234         || !EVP_DecryptUpdate(ctx, tmp, &outl, in, (int)(inlen - blocklen))
235 
236         /* Reset IV to original value */
237         || !EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL)
238         /* Decrypt again */
239         || !EVP_DecryptUpdate(ctx, tmp, &outl, tmp, (int)inlen))
240         goto err;
241     /* Check check bytes */
242     if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff) {
243         /* Check byte failure */
244         goto err;
245     }
246     if (inlen < (size_t)(tmp[0] - 4)) {
247         /* Invalid length value */
248         goto err;
249     }
250     *outlen = (size_t)tmp[0];
251     memcpy(out, tmp + 4, *outlen);
252     rv = 1;
253  err:
254     OPENSSL_clear_free(tmp, inlen);
255     return rv;
256 
257 }
258 
kek_wrap_key(unsigned char * out,size_t * outlen,const unsigned char * in,size_t inlen,EVP_CIPHER_CTX * ctx,const CMS_CTX * cms_ctx)259 static int kek_wrap_key(unsigned char *out, size_t *outlen,
260                         const unsigned char *in, size_t inlen,
261                         EVP_CIPHER_CTX *ctx, const CMS_CTX *cms_ctx)
262 {
263     size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx);
264     size_t olen;
265     int dummy;
266 
267     if (blocklen == 0)
268         return 0;
269 
270     /*
271      * First decide length of output buffer: need header and round up to
272      * multiple of block length.
273      */
274     olen = (inlen + 4 + blocklen - 1) / blocklen;
275     olen *= blocklen;
276     if (olen < 2 * blocklen) {
277         /* Key too small */
278         return 0;
279     }
280     if (inlen > 0xFF) {
281         /* Key too large */
282         return 0;
283     }
284     if (out) {
285         /* Set header */
286         out[0] = (unsigned char)inlen;
287         out[1] = in[0] ^ 0xFF;
288         out[2] = in[1] ^ 0xFF;
289         out[3] = in[2] ^ 0xFF;
290         memcpy(out + 4, in, inlen);
291         /* Add random padding to end */
292         if (olen > inlen + 4
293             && RAND_bytes_ex(ossl_cms_ctx_get0_libctx(cms_ctx), out + 4 + inlen,
294                              olen - 4 - inlen, 0) <= 0)
295             return 0;
296         /* Encrypt twice */
297         if (!EVP_EncryptUpdate(ctx, out, &dummy, out, (int)olen)
298             || !EVP_EncryptUpdate(ctx, out, &dummy, out, (int)olen))
299             return 0;
300     }
301 
302     *outlen = olen;
303 
304     return 1;
305 }
306 
307 /* Encrypt/Decrypt content key in PWRI recipient info */
308 
ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo * cms,CMS_RecipientInfo * ri,int en_de)309 int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms,
310                                       CMS_RecipientInfo *ri, int en_de)
311 {
312     CMS_EncryptedContentInfo *ec;
313     CMS_PasswordRecipientInfo *pwri;
314     int r = 0;
315     X509_ALGOR *algtmp, *kekalg = NULL;
316     EVP_CIPHER_CTX *kekctx = NULL;
317     char name[OSSL_MAX_NAME_SIZE];
318     EVP_CIPHER *kekcipher;
319     unsigned char *key = NULL;
320     size_t keylen;
321     const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms);
322 
323     ec = ossl_cms_get0_env_enc_content(cms);
324 
325     pwri = ri->d.pwri;
326 
327     if (pwri->pass == NULL) {
328         ERR_raise(ERR_LIB_CMS, CMS_R_NO_PASSWORD);
329         return 0;
330     }
331     algtmp = pwri->keyEncryptionAlgorithm;
332 
333     if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) {
334         ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
335         return 0;
336     }
337 
338     kekalg = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
339                                        algtmp->parameter);
340 
341     if (kekalg == NULL) {
342         ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
343         return 0;
344     }
345 
346     OBJ_obj2txt(name, sizeof(name), kekalg->algorithm, 0);
347     kekcipher = EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(cms_ctx), name,
348                                  ossl_cms_ctx_get0_propq(cms_ctx));
349 
350     if (kekcipher == NULL) {
351         ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER);
352         goto err;
353     }
354 
355     kekctx = EVP_CIPHER_CTX_new();
356     if (kekctx == NULL) {
357         ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
358         goto err;
359     }
360     /* Fixup cipher based on AlgorithmIdentifier to set IV etc */
361     if (!EVP_CipherInit_ex(kekctx, kekcipher, NULL, NULL, NULL, en_de))
362         goto err;
363     EVP_CIPHER_CTX_set_padding(kekctx, 0);
364     if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) {
365         ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
366         goto err;
367     }
368 
369     algtmp = pwri->keyDerivationAlgorithm;
370 
371     /* Finish password based key derivation to setup key in "ctx" */
372 
373     if (EVP_PBE_CipherInit_ex(algtmp->algorithm,
374                               (char *)pwri->pass, (int)pwri->passlen,
375                               algtmp->parameter, kekctx, en_de,
376                               cms_ctx->libctx, cms_ctx->propq) < 0) {
377         ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
378         goto err;
379     }
380 
381     /* Finally wrap/unwrap the key */
382 
383     if (en_de) {
384 
385         if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx, cms_ctx))
386             goto err;
387 
388         key = OPENSSL_malloc(keylen);
389 
390         if (key == NULL)
391             goto err;
392 
393         if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx, cms_ctx))
394             goto err;
395         pwri->encryptedKey->data = key;
396         pwri->encryptedKey->length = (int)keylen;
397     } else {
398         key = OPENSSL_malloc(pwri->encryptedKey->length);
399         if (key == NULL)
400             goto err;
401         if (!kek_unwrap_key(key, &keylen,
402                             pwri->encryptedKey->data,
403                             pwri->encryptedKey->length, kekctx)) {
404             ERR_raise(ERR_LIB_CMS, CMS_R_UNWRAP_FAILURE);
405             goto err;
406         }
407 
408         OPENSSL_clear_free(ec->key, ec->keylen);
409         ec->key = key;
410         ec->keylen = keylen;
411 
412     }
413 
414     r = 1;
415 
416  err:
417     EVP_CIPHER_free(kekcipher);
418     EVP_CIPHER_CTX_free(kekctx);
419 
420     if (!r)
421         OPENSSL_free(key);
422     X509_ALGOR_free(kekalg);
423 
424     return r;
425 
426 }
427