Coverage Report

Created: 2018-08-29 13:53

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