Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/crypto/cms/cms_kem.c
Line
Count
Source
1
/*
2
 * Copyright 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 <assert.h>
11
#include <limits.h>
12
#include <openssl/cms.h>
13
#include <openssl/core_names.h>
14
#include <openssl/err.h>
15
#include <openssl/decoder.h>
16
#include "internal/sizes.h"
17
#include "crypto/asn1.h"
18
#include "crypto/evp.h"
19
#include "cms_local.h"
20
21
static int kem_cms_decrypt(CMS_RecipientInfo *ri)
22
0
{
23
0
    uint32_t *kekLength;
24
0
    X509_ALGOR *wrap;
25
0
    EVP_PKEY_CTX *pctx;
26
0
    EVP_CIPHER_CTX *kekctx;
27
0
    uint32_t cipher_length;
28
0
    char name[OSSL_MAX_NAME_SIZE];
29
0
    EVP_CIPHER *kekcipher = NULL;
30
0
    int rv = 0;
31
32
0
    if (!ossl_cms_RecipientInfo_kemri_get0_alg(ri, &kekLength, &wrap))
33
0
        goto err;
34
35
0
    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
36
0
    if (pctx == NULL)
37
0
        goto err;
38
39
0
    kekctx = CMS_RecipientInfo_kemri_get0_ctx(ri);
40
0
    if (kekctx == NULL)
41
0
        goto err;
42
43
0
    OBJ_obj2txt(name, sizeof(name), wrap->algorithm, 0);
44
0
    kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, pctx->propquery);
45
0
    if (kekcipher == NULL || EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
46
0
        goto err;
47
0
    if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
48
0
        goto err;
49
0
    if (EVP_CIPHER_asn1_to_param(kekctx, wrap->parameter) <= 0)
50
0
        goto err;
51
52
0
    cipher_length = EVP_CIPHER_CTX_get_key_length(kekctx);
53
0
    if (cipher_length != *kekLength) {
54
0
        ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
55
0
        goto err;
56
0
    }
57
58
0
    rv = 1;
59
0
err:
60
0
    EVP_CIPHER_free(kekcipher);
61
0
    return rv;
62
0
}
63
64
static int kem_cms_encrypt(CMS_RecipientInfo *ri)
65
0
{
66
0
    uint32_t *kekLength;
67
0
    X509_ALGOR *wrap;
68
0
    X509_ALGOR *kdf;
69
0
    EVP_PKEY_CTX *pctx;
70
0
    EVP_PKEY *pkey;
71
0
    int security_bits;
72
0
    const ASN1_OBJECT *kdf_obj = NULL;
73
0
    unsigned char kemri_x509_algor[OSSL_MAX_ALGORITHM_ID_SIZE];
74
0
    OSSL_PARAM params[2];
75
0
    X509_ALGOR *x509_algor = NULL;
76
0
    EVP_CIPHER_CTX *kekctx;
77
0
    int wrap_nid;
78
0
    int rv = 0;
79
80
0
    if (!ossl_cms_RecipientInfo_kemri_get0_alg(ri, &kekLength, &wrap))
81
0
        goto err;
82
83
0
    kdf = CMS_RecipientInfo_kemri_get0_kdf_alg(ri);
84
0
    if (kdf == NULL)
85
0
        goto err;
86
87
0
    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
88
0
    if (pctx == NULL)
89
0
        goto err;
90
91
0
    pkey = EVP_PKEY_CTX_get0_pkey(pctx);
92
0
    if (pkey == NULL)
93
0
        goto err;
94
95
0
    security_bits = EVP_PKEY_get_security_bits(pkey);
96
0
    if (security_bits == 0)
97
0
        goto err;
98
99
0
    X509_ALGOR_get0(&kdf_obj, NULL, NULL, kdf);
100
0
    if (kdf_obj == NULL || OBJ_obj2nid(kdf_obj) == NID_undef) {
101
        /*
102
         * If the KDF OID hasn't already been set, then query the provider
103
         * for a default KDF.
104
         */
105
0
        params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_CMS_KEMRI_KDF_ALGORITHM,
106
0
            kemri_x509_algor, sizeof(kemri_x509_algor));
107
0
        params[1] = OSSL_PARAM_construct_end();
108
0
        if (!EVP_PKEY_get_params(pkey, params))
109
0
            goto err;
110
0
        if (OSSL_PARAM_modified(&params[0])) {
111
0
            const unsigned char *p = kemri_x509_algor;
112
113
0
            x509_algor = d2i_X509_ALGOR(NULL, &p, (long)params[0].return_size);
114
0
            if (x509_algor == NULL)
115
0
                goto err;
116
0
            if (!X509_ALGOR_copy(kdf, x509_algor))
117
0
                goto err;
118
0
        } else {
119
0
            if (!X509_ALGOR_set0(kdf, OBJ_nid2obj(NID_HKDF_SHA256), V_ASN1_UNDEF, NULL))
120
0
                return 0;
121
0
        }
122
0
    }
123
124
    /* Get wrap NID */
125
0
    kekctx = CMS_RecipientInfo_kemri_get0_ctx(ri);
126
0
    if (kekctx == NULL)
127
0
        goto err;
128
0
    *kekLength = EVP_CIPHER_CTX_get_key_length(kekctx);
129
0
    wrap_nid = EVP_CIPHER_CTX_get_type(kekctx);
130
131
    /* Package wrap algorithm in an AlgorithmIdentifier */
132
0
    ASN1_OBJECT_free(wrap->algorithm);
133
0
    ASN1_TYPE_free(wrap->parameter);
134
0
    wrap->algorithm = OBJ_nid2obj(wrap_nid);
135
0
    wrap->parameter = ASN1_TYPE_new();
136
0
    if (wrap->parameter == NULL)
137
0
        goto err;
138
0
    if (EVP_CIPHER_param_to_asn1(kekctx, wrap->parameter) <= 0) {
139
0
        ASN1_TYPE_free(wrap->parameter);
140
0
        wrap->parameter = NULL;
141
0
        goto err;
142
0
    }
143
0
    if (ASN1_TYPE_get(wrap->parameter) == NID_undef) {
144
0
        ASN1_TYPE_free(wrap->parameter);
145
0
        wrap->parameter = NULL;
146
0
    }
147
148
0
    rv = 1;
149
0
err:
150
0
    X509_ALGOR_free(x509_algor);
151
0
    return rv;
152
0
}
153
154
int ossl_cms_kem_envelope(CMS_RecipientInfo *ri, int decrypt)
155
0
{
156
0
    assert(decrypt == 0 || decrypt == 1);
157
158
0
    if (decrypt == 1)
159
0
        return kem_cms_decrypt(ri);
160
161
0
    if (decrypt == 0)
162
0
        return kem_cms_encrypt(ri);
163
164
0
    ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
165
0
    return 0;
166
0
}