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