Bug Summary

File:src/lib/libcrypto/cms/cms_pwri.c
Warning:line 112, column 3
Value stored to 'pbe_nid' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cms_pwri.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libcrypto/obj -resource-dir /usr/local/llvm16/lib/clang/16 -D LIBRESSL_INTERNAL -D HAVE_FUNOPEN -I /usr/src/lib/libcrypto -I /usr/src/lib/libcrypto/arch/amd64 -I /usr/src/lib/libcrypto/asn1 -I /usr/src/lib/libcrypto/bio -I /usr/src/lib/libcrypto/bn -I /usr/src/lib/libcrypto/bn/arch/amd64 -I /usr/src/lib/libcrypto/bytestring -I /usr/src/lib/libcrypto/curve25519 -I /usr/src/lib/libcrypto/dh -I /usr/src/lib/libcrypto/dsa -I /usr/src/lib/libcrypto/ec -I /usr/src/lib/libcrypto/ecdsa -I /usr/src/lib/libcrypto/evp -I /usr/src/lib/libcrypto/hidden -I /usr/src/lib/libcrypto/hmac -I /usr/src/lib/libcrypto/kdf -I /usr/src/lib/libcrypto/modes -I /usr/src/lib/libcrypto/ocsp -I /usr/src/lib/libcrypto/pkcs12 -I /usr/src/lib/libcrypto/rsa -I /usr/src/lib/libcrypto/sha -I /usr/src/lib/libcrypto/ts -I /usr/src/lib/libcrypto/x509 -I /usr/src/lib/libcrypto/obj -D AES_ASM -D BSAES_ASM -D VPAES_ASM -D OPENSSL_IA32_SSE2 -D RSA_ASM -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D MD5_ASM -D GHASH_ASM -D RC4_MD5_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D WHIRLPOOL_ASM -D OPENSSL_CPUID_OBJ -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcrypto/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/lib/libcrypto/cms/cms_pwri.c
1/* $OpenBSD: cms_pwri.c,v 1.30 2023/12/20 18:38:19 tb Exp $ */
2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4 * project.
5 */
6/* ====================================================================
7 * Copyright (c) 2009 The OpenSSL Project. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 * acknowledgment:
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 */
54
55#include <sys/types.h>
56
57#include <stdlib.h>
58#include <string.h>
59
60#include <openssl/asn1.h>
61#include <openssl/err.h>
62#include <openssl/evp.h>
63#include <openssl/cms.h>
64#include <openssl/objects.h>
65#include <openssl/x509.h>
66
67#include "cms_local.h"
68#include "evp_local.h"
69
70int
71CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, unsigned char *pass,
72 ssize_t passlen)
73{
74 CMS_PasswordRecipientInfo *pwri;
75
76 if (ri->type != CMS_RECIPINFO_PASS3) {
77 CMSerror(CMS_R_NOT_PWRI)ERR_put_error(46,(0xfff),(177),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,77)
;
78 return 0;
79 }
80
81 pwri = ri->d.pwri;
82 pwri->pass = pass;
83 if (pass && passlen < 0)
84 passlen = strlen((char *)pass);
85 pwri->passlen = passlen;
86
87 return 1;
88}
89LCRYPTO_ALIAS(CMS_RecipientInfo_set0_password)asm("");
90
91CMS_RecipientInfo *
92CMS_add0_recipient_password(CMS_ContentInfo *cms, int iter, int wrap_nid,
93 int pbe_nid, unsigned char *pass, ssize_t passlen,
94 const EVP_CIPHER *kekciph)
95{
96 CMS_RecipientInfo *ri = NULL((void *)0);
97 CMS_EnvelopedData *env;
98 CMS_PasswordRecipientInfo *pwri;
99 EVP_CIPHER_CTX *ctx = NULL((void *)0);
100 X509_ALGOR *encalg = NULL((void *)0);
101 unsigned char iv[EVP_MAX_IV_LENGTH16];
102 int ivlen;
103
104 env = cms_get0_enveloped(cms);
105 if (!env)
106 return NULL((void *)0);
107
108 if (wrap_nid <= 0)
109 wrap_nid = NID_id_alg_PWRI_KEK893;
110
111 if (pbe_nid <= 0)
112 pbe_nid = NID_id_pbkdf269;
Value stored to 'pbe_nid' is never read
113
114 /* Get from enveloped data */
115 if (kekciph == NULL((void *)0))
116 kekciph = env->encryptedContentInfo->cipher;
117
118 if (kekciph == NULL((void *)0)) {
119 CMSerror(CMS_R_NO_CIPHER)ERR_put_error(46,(0xfff),(126),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,119)
;
120 return NULL((void *)0);
121 }
122 if (wrap_nid != NID_id_alg_PWRI_KEK893) {
123 CMSerror(CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM)ERR_put_error(46,(0xfff),(179),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,123)
;
124 return NULL((void *)0);
125 }
126
127 /* Setup algorithm identifier for cipher */
128 encalg = X509_ALGOR_new();
129 if (encalg == NULL((void *)0)) {
130 goto merr;
131 }
132
133 if ((ctx = EVP_CIPHER_CTX_new()) == NULL((void *)0))
134 goto merr;
135
136 if (EVP_EncryptInit_ex(ctx, kekciph, NULL((void *)0), NULL((void *)0), NULL((void *)0)) <= 0) {
137 CMSerror(ERR_R_EVP_LIB)ERR_put_error(46,(0xfff),(6),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,137)
;
138 goto err;
139 }
140
141 ivlen = EVP_CIPHER_CTX_iv_length(ctx);
142
143 if (ivlen > 0) {
144 arc4random_buf(iv, ivlen);
145 if (EVP_EncryptInit_ex(ctx, NULL((void *)0), NULL((void *)0), NULL((void *)0), iv) <= 0) {
146 CMSerror(ERR_R_EVP_LIB)ERR_put_error(46,(0xfff),(6),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,146)
;
147 goto err;
148 }
149 encalg->parameter = ASN1_TYPE_new();
150 if (!encalg->parameter) {
151 CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,151)
;
152 goto err;
153 }
154 if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) {
155 CMSerror(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR)ERR_put_error(46,(0xfff),(102),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,155)
;
156 goto err;
157 }
158 }
159
160 encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx)EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(ctx)));
161
162 EVP_CIPHER_CTX_free(ctx);
163 ctx = NULL((void *)0);
164
165 /* Initialize recipient info */
166 ri = (CMS_RecipientInfo *)ASN1_item_new(&CMS_RecipientInfo_it);
167 if (ri == NULL((void *)0))
168 goto merr;
169
170 ri->d.pwri = (CMS_PasswordRecipientInfo *)ASN1_item_new(&CMS_PasswordRecipientInfo_it);
171 if (ri->d.pwri == NULL((void *)0))
172 goto merr;
173 ri->type = CMS_RECIPINFO_PASS3;
174
175 pwri = ri->d.pwri;
176 /* Since this is overwritten, free up empty structure already there */
177 X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
178 pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
179 if (pwri->keyEncryptionAlgorithm == NULL((void *)0))
180 goto merr;
181 pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid);
182 pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new();
183 if (pwri->keyEncryptionAlgorithm->parameter == NULL((void *)0))
184 goto merr;
185
186 if (!ASN1_item_pack(encalg, &X509_ALGOR_it,
187 &pwri->keyEncryptionAlgorithm->parameter->value.sequence))
188 goto merr;
189 pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE16;
190
191 X509_ALGOR_free(encalg);
192 encalg = NULL((void *)0);
193
194 /* Setup PBE algorithm */
195
196 pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL((void *)0), 0, -1, -1);
197
198 if (!pwri->keyDerivationAlgorithm)
199 goto err;
200
201 CMS_RecipientInfo_set0_password(ri, pass, passlen);
202 pwri->version = 0;
203
204 if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)sk_push(((_STACK*) (1 ? (env->recipientInfos) : (struct stack_st_CMS_RecipientInfo
*)0)), ((void*) (1 ? (ri) : (CMS_RecipientInfo*)0)))
)
205 goto merr;
206
207 return ri;
208
209 merr:
210 CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,210)
;
211 err:
212 EVP_CIPHER_CTX_free(ctx);
213 if (ri)
214 ASN1_item_free((ASN1_VALUE *)ri, &CMS_RecipientInfo_it);
215 X509_ALGOR_free(encalg);
216
217 return NULL((void *)0);
218}
219LCRYPTO_ALIAS(CMS_add0_recipient_password)asm("");
220
221/*
222 * This is an implementation of the key wrapping mechanism in RFC3211, at
223 * some point this should go into EVP.
224 */
225
226static int
227kek_unwrap_key(unsigned char *out, size_t *outlen, const unsigned char *in,
228 size_t inlen, EVP_CIPHER_CTX *ctx)
229{
230 size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
231 unsigned char *tmp;
232 int outl, rv = 0;
233
234 if (inlen < 2 * blocklen) {
235 /* too small */
236 return 0;
237 }
238 if (inlen % blocklen) {
239 /* Invalid size */
240 return 0;
241 }
242 if ((tmp = malloc(inlen)) == NULL((void *)0)) {
243 CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,243)
;
244 return 0;
245 }
246
247 /* setup IV by decrypting last two blocks */
248 if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl,
249 in + inlen - 2 * blocklen, blocklen * 2)
250 /*
251 * Do a decrypt of last decrypted block to set IV to correct value
252 * output it to start of buffer so we don't corrupt decrypted block
253 * this works because buffer is at least two block lengths long.
254 */
255 || !EVP_DecryptUpdate(ctx, tmp, &outl, tmp + inlen - blocklen, blocklen)
256 /* Can now decrypt first n - 1 blocks */
257 || !EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen)
258
259 /* Reset IV to original value */
260 || !EVP_DecryptInit_ex(ctx, NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0))
261 /* Decrypt again */
262 || !EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen))
263 goto err;
264 /* Check check bytes */
265 if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff) {
266 /* Check byte failure */
267 goto err;
268 }
269 if (inlen < (size_t)(tmp[0] - 4)) {
270 /* Invalid length value */
271 goto err;
272 }
273 *outlen = (size_t)tmp[0];
274 memcpy(out, tmp + 4, *outlen);
275 rv = 1;
276
277 err:
278 freezero(tmp, inlen);
279
280 return rv;
281}
282
283static int
284kek_wrap_key(unsigned char *out, size_t *outlen, const unsigned char *in,
285 size_t inlen, EVP_CIPHER_CTX *ctx)
286{
287 size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
288 size_t olen;
289 int dummy;
290
291 /*
292 * First decide length of output buffer: need header and round up to
293 * multiple of block length.
294 */
295 olen = (inlen + 4 + blocklen - 1) / blocklen;
296 olen *= blocklen;
297 if (olen < 2 * blocklen) {
298 /* Key too small */
299 return 0;
300 }
301 if (inlen > 0xFF) {
302 /* Key too large */
303 return 0;
304 }
305 if (out) {
306 /* Set header */
307 out[0] = (unsigned char)inlen;
308 out[1] = in[0] ^ 0xFF;
309 out[2] = in[1] ^ 0xFF;
310 out[3] = in[2] ^ 0xFF;
311 memcpy(out + 4, in, inlen);
312 /* Add random padding to end */
313 if (olen > inlen + 4)
314 arc4random_buf(out + 4 + inlen, olen - 4 - inlen);
315 /* Encrypt twice */
316 if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen) ||
317 !EVP_EncryptUpdate(ctx, out, &dummy, out, olen))
318 return 0;
319 }
320
321 *outlen = olen;
322
323 return 1;
324}
325
326/* Encrypt/Decrypt content key in PWRI recipient info */
327
328int
329cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
330 int en_de)
331{
332 CMS_EncryptedContentInfo *ec;
333 CMS_PasswordRecipientInfo *pwri;
334 int r = 0;
335 X509_ALGOR *algtmp, *kekalg = NULL((void *)0);
336 EVP_CIPHER_CTX *kekctx = NULL((void *)0);
337 const EVP_CIPHER *kekcipher;
338 unsigned char *key = NULL((void *)0);
339 size_t keylen;
340
341 ec = cms->d.envelopedData->encryptedContentInfo;
342
343 pwri = ri->d.pwri;
344
345 if (!pwri->pass) {
346 CMSerror(CMS_R_NO_PASSWORD)ERR_put_error(46,(0xfff),(178),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,346)
;
347 return 0;
348 }
349 algtmp = pwri->keyEncryptionAlgorithm;
350
351 if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK893) {
352 CMSerror(CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM)ERR_put_error(46,(0xfff),(179),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,352)
;
353 return 0;
354 }
355
356 if (algtmp->parameter != NULL((void *)0) &&
357 algtmp->parameter->type == V_ASN1_SEQUENCE16 &&
358 algtmp->parameter->value.sequence != NULL((void *)0))
359 kekalg = ASN1_item_unpack(algtmp->parameter->value.sequence,
360 &X509_ALGOR_it);
361
362 if (kekalg == NULL((void *)0)) {
363 CMSerror(CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER)ERR_put_error(46,(0xfff),(176),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,363)
;
364 return 0;
365 }
366
367 kekcipher = EVP_get_cipherbyobj(kekalg->algorithm)EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(kekalg->algorithm
)))
;
368 if (!kekcipher) {
369 CMSerror(CMS_R_UNKNOWN_CIPHER)ERR_put_error(46,(0xfff),(148),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,369)
;
370 return 0;
371 }
372
373 kekctx = EVP_CIPHER_CTX_new();
374 if (kekctx == NULL((void *)0)) {
375 CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,375)
;
376 return 0;
377 }
378 /* Fixup cipher based on AlgorithmIdentifier to set IV etc */
379 if (!EVP_CipherInit_ex(kekctx, kekcipher, NULL((void *)0), NULL((void *)0), NULL((void *)0), en_de))
380 goto err;
381 EVP_CIPHER_CTX_set_padding(kekctx, 0);
382 if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) {
383 CMSerror(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR)ERR_put_error(46,(0xfff),(102),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,383)
;
384 goto err;
385 }
386
387 algtmp = pwri->keyDerivationAlgorithm;
388
389 /* Finish password based key derivation to setup key in "ctx" */
390
391 if (EVP_PBE_CipherInit(algtmp->algorithm, (char *)pwri->pass,
392 pwri->passlen, algtmp->parameter, kekctx, en_de) < 0) {
393 CMSerror(ERR_R_EVP_LIB)ERR_put_error(46,(0xfff),(6),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,393)
;
394 goto err;
395 }
396
397 /* Finally wrap/unwrap the key */
398
399 if (en_de) {
400 if (!kek_wrap_key(NULL((void *)0), &keylen, ec->key, ec->keylen, kekctx))
401 goto err;
402
403 key = malloc(keylen);
404 if (key == NULL((void *)0))
405 goto err;
406
407 if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx))
408 goto err;
409 pwri->encryptedKey->data = key;
410 pwri->encryptedKey->length = keylen;
411 } else {
412 key = malloc(pwri->encryptedKey->length);
413 if (key == NULL((void *)0)) {
414 CMSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(46,(0xfff),((1|64)),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,414)
;
415 goto err;
416 }
417 if (!kek_unwrap_key(key, &keylen, pwri->encryptedKey->data,
418 pwri->encryptedKey->length, kekctx)) {
419 CMSerror(CMS_R_UNWRAP_FAILURE)ERR_put_error(46,(0xfff),(180),"/usr/src/lib/libcrypto/cms/cms_pwri.c"
,419)
;
420 goto err;
421 }
422
423 freezero(ec->key, ec->keylen);
424 ec->key = key;
425 ec->keylen = keylen;
426 }
427
428 r = 1;
429
430 err:
431 EVP_CIPHER_CTX_free(kekctx);
432 if (!r)
433 free(key);
434 X509_ALGOR_free(kekalg);
435
436 return r;
437}