2 * Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved.
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
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"
22 int CMS_RecipientInfo_set0_password(CMS_RecipientInfo
*ri
,
23 unsigned char *pass
, ossl_ssize_t passlen
)
25 CMS_PasswordRecipientInfo
*pwri
;
26 if (ri
->type
!= CMS_RECIPINFO_PASS
) {
27 ERR_raise(ERR_LIB_CMS
, CMS_R_NOT_PWRI
);
33 if (pass
&& passlen
< 0)
34 passlen
= strlen((char *)pass
);
35 pwri
->passlen
= passlen
;
39 CMS_RecipientInfo
*CMS_add0_recipient_password(CMS_ContentInfo
*cms
,
40 int iter
, int wrap_nid
,
44 const EVP_CIPHER
*kekciph
)
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
];
54 const CMS_CTX
*cms_ctx
= ossl_cms_get0_cmsctx(cms
);
56 ec
= ossl_cms_get0_env_enc_content(cms
);
59 ris
= CMS_get0_RecipientInfos(cms
);
64 wrap_nid
= NID_id_alg_PWRI_KEK
;
67 pbe_nid
= NID_id_pbkdf2
;
69 /* Get from enveloped data */
73 if (kekciph
== NULL
) {
74 ERR_raise(ERR_LIB_CMS
, CMS_R_NO_CIPHER
);
77 if (wrap_nid
!= NID_id_alg_PWRI_KEK
) {
78 ERR_raise(ERR_LIB_CMS
, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM
);
82 /* Setup algorithm identifier for cipher */
83 encalg
= X509_ALGOR_new();
85 ERR_raise(ERR_LIB_CMS
, ERR_R_ASN1_LIB
);
88 ctx
= EVP_CIPHER_CTX_new();
90 ERR_raise(ERR_LIB_CMS
, ERR_R_EVP_LIB
);
94 if (EVP_EncryptInit_ex(ctx
, kekciph
, NULL
, NULL
, NULL
) <= 0) {
95 ERR_raise(ERR_LIB_CMS
, ERR_R_EVP_LIB
);
99 ivlen
= EVP_CIPHER_CTX_get_iv_length(ctx
);
101 ERR_raise(ERR_LIB_CMS
, ERR_R_EVP_LIB
);
106 if (RAND_bytes_ex(ossl_cms_ctx_get0_libctx(cms_ctx
), iv
, ivlen
, 0) <= 0)
108 if (EVP_EncryptInit_ex(ctx
, NULL
, NULL
, NULL
, iv
) <= 0) {
109 ERR_raise(ERR_LIB_CMS
, ERR_R_EVP_LIB
);
112 encalg
->parameter
= ASN1_TYPE_new();
113 if (!encalg
->parameter
) {
114 ERR_raise(ERR_LIB_CMS
, ERR_R_ASN1_LIB
);
117 if (EVP_CIPHER_param_to_asn1(ctx
, encalg
->parameter
) <= 0) {
118 ERR_raise(ERR_LIB_CMS
, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR
);
123 encalg
->algorithm
= OBJ_nid2obj(EVP_CIPHER_CTX_get_type(ctx
));
125 EVP_CIPHER_CTX_free(ctx
);
128 /* Initialize recipient info */
129 ri
= M_ASN1_new_of(CMS_RecipientInfo
);
131 ERR_raise(ERR_LIB_CMS
, ERR_R_ASN1_LIB
);
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
);
140 ri
->type
= CMS_RECIPINFO_PASS
;
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
);
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
);
158 if (!ASN1_item_pack(encalg
, ASN1_ITEM_rptr(X509_ALGOR
),
159 &pwri
->keyEncryptionAlgorithm
->parameter
->
161 ERR_raise(ERR_LIB_CMS
, ERR_R_ASN1_LIB
);
164 pwri
->keyEncryptionAlgorithm
->parameter
->type
= V_ASN1_SEQUENCE
;
166 X509_ALGOR_free(encalg
);
169 /* Setup PBE algorithm */
171 pwri
->keyDerivationAlgorithm
= PKCS5_pbkdf2_set(iter
, NULL
, 0, -1, -1);
173 if (pwri
->keyDerivationAlgorithm
== NULL
)
176 CMS_RecipientInfo_set0_password(ri
, pass
, passlen
);
179 if (!sk_CMS_RecipientInfo_push(ris
, ri
)) {
180 ERR_raise(ERR_LIB_CMS
, ERR_R_CRYPTO_LIB
);
187 EVP_CIPHER_CTX_free(ctx
);
189 M_ASN1_free_of(ri
, CMS_RecipientInfo
);
190 X509_ALGOR_free(encalg
);
196 * This is an implementation of the key wrapping mechanism in RFC3211, at
197 * some point this should go into EVP.
200 static int kek_unwrap_key(unsigned char *out
, size_t *outlen
,
201 const unsigned char *in
, size_t inlen
,
204 size_t blocklen
= EVP_CIPHER_CTX_get_block_size(ctx
);
211 if (inlen
< 2 * blocklen
) {
215 if (inlen
% blocklen
) {
219 if ((tmp
= OPENSSL_malloc(inlen
)) == NULL
)
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)
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.
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
)
234 /* Reset IV to original value */
235 || !EVP_DecryptInit_ex(ctx
, NULL
, NULL
, NULL
, NULL
)
237 || !EVP_DecryptUpdate(ctx
, tmp
, &outl
, tmp
, inlen
))
239 /* Check check bytes */
240 if (((tmp
[1] ^ tmp
[4]) & (tmp
[2] ^ tmp
[5]) & (tmp
[3] ^ tmp
[6])) != 0xff) {
241 /* Check byte failure */
244 if (inlen
< (size_t)(tmp
[0] - 4)) {
245 /* Invalid length value */
248 *outlen
= (size_t)tmp
[0];
249 memcpy(out
, tmp
+ 4, *outlen
);
252 OPENSSL_clear_free(tmp
, inlen
);
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
)
261 size_t blocklen
= EVP_CIPHER_CTX_get_block_size(ctx
);
269 * First decide length of output buffer: need header and round up to
270 * multiple of block length.
272 olen
= (inlen
+ 4 + blocklen
- 1) / blocklen
;
274 if (olen
< 2 * blocklen
) {
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 */
291 && RAND_bytes_ex(ossl_cms_ctx_get0_libctx(cms_ctx
), out
+ 4 + inlen
,
292 olen
- 4 - inlen
, 0) <= 0)
295 if (!EVP_EncryptUpdate(ctx
, out
, &dummy
, out
, olen
)
296 || !EVP_EncryptUpdate(ctx
, out
, &dummy
, out
, olen
))
305 /* Encrypt/Decrypt content key in PWRI recipient info */
307 int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo
*cms
,
308 CMS_RecipientInfo
*ri
, int en_de
)
310 CMS_EncryptedContentInfo
*ec
;
311 CMS_PasswordRecipientInfo
*pwri
;
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
;
319 const CMS_CTX
*cms_ctx
= ossl_cms_get0_cmsctx(cms
);
321 ec
= ossl_cms_get0_env_enc_content(cms
);
325 if (pwri
->pass
== NULL
) {
326 ERR_raise(ERR_LIB_CMS
, CMS_R_NO_PASSWORD
);
329 algtmp
= pwri
->keyEncryptionAlgorithm
;
331 if (!algtmp
|| OBJ_obj2nid(algtmp
->algorithm
) != NID_id_alg_PWRI_KEK
) {
332 ERR_raise(ERR_LIB_CMS
, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM
);
336 kekalg
= ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR
),
339 if (kekalg
== NULL
) {
340 ERR_raise(ERR_LIB_CMS
, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER
);
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
));
348 if (kekcipher
== NULL
) {
349 ERR_raise(ERR_LIB_CMS
, CMS_R_UNKNOWN_CIPHER
);
353 kekctx
= EVP_CIPHER_CTX_new();
354 if (kekctx
== NULL
) {
355 ERR_raise(ERR_LIB_CMS
, ERR_R_EVP_LIB
);
358 /* Fixup cipher based on AlgorithmIdentifier to set IV etc */
359 if (!EVP_CipherInit_ex(kekctx
, kekcipher
, NULL
, NULL
, NULL
, en_de
))
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
);
367 algtmp
= pwri
->keyDerivationAlgorithm
;
369 /* Finish password based key derivation to setup key in "ctx" */
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
);
378 /* Finally wrap/unwrap the key */
382 if (!kek_wrap_key(NULL
, &keylen
, ec
->key
, ec
->keylen
, kekctx
, cms_ctx
))
385 key
= OPENSSL_malloc(keylen
);
390 if (!kek_wrap_key(key
, &keylen
, ec
->key
, ec
->keylen
, kekctx
, cms_ctx
))
392 pwri
->encryptedKey
->data
= key
;
393 pwri
->encryptedKey
->length
= keylen
;
395 key
= OPENSSL_malloc(pwri
->encryptedKey
->length
);
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
);
405 OPENSSL_clear_free(ec
->key
, ec
->keylen
);
414 EVP_CIPHER_free(kekcipher
);
415 EVP_CIPHER_CTX_free(kekctx
);
419 X509_ALGOR_free(kekalg
);