Coverage Report

Created: 2018-08-29 13:53

/src/openssl/crypto/cms/cms_enc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2008-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 "cms_lcl.h"
18
19
/* CMS EncryptedData Utilities */
20
21
/* Return BIO based on EncryptedContentInfo and key */
22
23
BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
24
0
{
25
0
    BIO *b;
26
0
    EVP_CIPHER_CTX *ctx;
27
0
    const EVP_CIPHER *ciph;
28
0
    X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
29
0
    unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
30
0
    unsigned char *tkey = NULL;
31
0
    size_t tkeylen = 0;
32
0
33
0
    int ok = 0;
34
0
35
0
    int enc, keep_key = 0;
36
0
37
0
    enc = ec->cipher ? 1 : 0;
38
0
39
0
    b = BIO_new(BIO_f_cipher());
40
0
    if (b == NULL) {
41
0
        CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
42
0
        return NULL;
43
0
    }
44
0
45
0
    BIO_get_cipher_ctx(b, &ctx);
46
0
47
0
    if (enc) {
48
0
        ciph = ec->cipher;
49
0
        /*
50
0
         * If not keeping key set cipher to NULL so subsequent calls decrypt.
51
0
         */
52
0
        if (ec->key)
53
0
            ec->cipher = NULL;
54
0
    } else {
55
0
        ciph = EVP_get_cipherbyobj(calg->algorithm);
56
0
57
0
        if (!ciph) {
58
0
            CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER);
59
0
            goto err;
60
0
        }
61
0
    }
62
0
63
0
    if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) {
64
0
        CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
65
0
               CMS_R_CIPHER_INITIALISATION_ERROR);
66
0
        goto err;
67
0
    }
68
0
69
0
    if (enc) {
70
0
        int ivlen;
71
0
        calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
72
0
        /* Generate a random IV if we need one */
73
0
        ivlen = EVP_CIPHER_CTX_iv_length(ctx);
74
0
        if (ivlen > 0) {
75
0
            if (RAND_bytes(iv, ivlen) <= 0)
76
0
                goto err;
77
0
            piv = iv;
78
0
        }
79
0
    } else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) {
80
0
        CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
81
0
               CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
82
0
        goto err;
83
0
    }
84
0
    tkeylen = EVP_CIPHER_CTX_key_length(ctx);
85
0
    /* Generate random session key */
86
0
    if (!enc || !ec->key) {
87
0
        tkey = OPENSSL_malloc(tkeylen);
88
0
        if (tkey == NULL) {
89
0
            CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
90
0
            goto err;
91
0
        }
92
0
        if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0)
93
0
            goto err;
94
0
    }
95
0
96
0
    if (!ec->key) {
97
0
        ec->key = tkey;
98
0
        ec->keylen = tkeylen;
99
0
        tkey = NULL;
100
0
        if (enc)
101
0
            keep_key = 1;
102
0
        else
103
0
            ERR_clear_error();
104
0
105
0
    }
106
0
107
0
    if (ec->keylen != tkeylen) {
108
0
        /* If necessary set key length */
109
0
        if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) {
110
0
            /*
111
0
             * Only reveal failure if debugging so we don't leak information
112
0
             * which may be useful in MMA.
113
0
             */
114
0
            if (enc || ec->debug) {
115
0
                CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
116
0
                       CMS_R_INVALID_KEY_LENGTH);
117
0
                goto err;
118
0
            } else {
119
0
                /* Use random key */
120
0
                OPENSSL_clear_free(ec->key, ec->keylen);
121
0
                ec->key = tkey;
122
0
                ec->keylen = tkeylen;
123
0
                tkey = NULL;
124
0
                ERR_clear_error();
125
0
            }
126
0
        }
127
0
    }
128
0
129
0
    if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) {
130
0
        CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
131
0
               CMS_R_CIPHER_INITIALISATION_ERROR);
132
0
        goto err;
133
0
    }
134
0
    if (enc) {
135
0
        calg->parameter = ASN1_TYPE_new();
136
0
        if (calg->parameter == NULL) {
137
0
            CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
138
0
            goto err;
139
0
        }
140
0
        if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) {
141
0
            CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
142
0
                   CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
143
0
            goto err;
144
0
        }
145
0
        /* If parameter type not set omit parameter */
146
0
        if (calg->parameter->type == V_ASN1_UNDEF) {
147
0
            ASN1_TYPE_free(calg->parameter);
148
0
            calg->parameter = NULL;
149
0
        }
150
0
    }
151
0
    ok = 1;
152
0
153
0
 err:
154
0
    if (!keep_key || !ok) {
155
0
        OPENSSL_clear_free(ec->key, ec->keylen);
156
0
        ec->key = NULL;
157
0
    }
158
0
    OPENSSL_clear_free(tkey, tkeylen);
159
0
    if (ok)
160
0
        return b;
161
0
    BIO_free(b);
162
0
    return NULL;
163
0
}
164
165
int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
166
                              const EVP_CIPHER *cipher,
167
                              const unsigned char *key, size_t keylen)
168
0
{
169
0
    ec->cipher = cipher;
170
0
    if (key) {
171
0
        if ((ec->key = OPENSSL_malloc(keylen)) == NULL) {
172
0
            CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT, ERR_R_MALLOC_FAILURE);
173
0
            return 0;
174
0
        }
175
0
        memcpy(ec->key, key, keylen);
176
0
    }
177
0
    ec->keylen = keylen;
178
0
    if (cipher)
179
0
        ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
180
0
    return 1;
181
0
}
182
183
int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
184
                               const unsigned char *key, size_t keylen)
185
0
{
186
0
    CMS_EncryptedContentInfo *ec;
187
0
    if (!key || !keylen) {
188
0
        CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY);
189
0
        return 0;
190
0
    }
191
0
    if (ciph) {
192
0
        cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData);
193
0
        if (!cms->d.encryptedData) {
194
0
            CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, ERR_R_MALLOC_FAILURE);
195
0
            return 0;
196
0
        }
197
0
        cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted);
198
0
        cms->d.encryptedData->version = 0;
199
0
    } else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) {
200
0
        CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NOT_ENCRYPTED_DATA);
201
0
        return 0;
202
0
    }
203
0
    ec = cms->d.encryptedData->encryptedContentInfo;
204
0
    return cms_EncryptedContent_init(ec, ciph, key, keylen);
205
0
}
206
207
BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms)
208
0
{
209
0
    CMS_EncryptedData *enc = cms->d.encryptedData;
210
0
    if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
211
0
        enc->version = 2;
212
0
    return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
213
0
}