Bug Summary

File:src/lib/libcrypto/pem/pem_lib.c
Warning:line 572, column 13
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage

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 pem_lib.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/pem/pem_lib.c
1/* $OpenBSD: pem_lib.c,v 1.55 2023/11/29 21:35:57 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <ctype.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <string.h>
63
64#include <openssl/opensslconf.h>
65
66#include <openssl/buffer.h>
67#include <openssl/err.h>
68#include <openssl/evp.h>
69#include <openssl/objects.h>
70#include <openssl/pem.h>
71#include <openssl/pkcs12.h>
72#include <openssl/x509.h>
73
74#ifndef OPENSSL_NO_DES
75#include <openssl/des.h>
76#endif
77
78#include "asn1_local.h"
79#include "evp_local.h"
80
81#define MIN_LENGTH4 4
82
83static int load_iv(char **fromp, unsigned char *to, int num);
84static int check_pem(const char *nm, const char *name);
85int pem_check_suffix(const char *pem_str, const char *suffix);
86
87/* XXX LSSL ABI XXX return value and `num' ought to be size_t */
88int
89PEM_def_callback(char *buf, int num, int w, void *key)
90{
91 size_t l;
92 int i;
93 const char *prompt;
94
95 if (num < 0)
96 return -1;
97
98 if (key) {
99 l = strlen(key);
100 if (l > (size_t)num)
101 l = (size_t)num;
102 memcpy(buf, key, l);
103 return (int)l;
104 }
105
106 prompt = EVP_get_pw_prompt();
107 if (prompt == NULL((void *)0))
108 prompt = "Enter PEM pass phrase:";
109
110 for (;;) {
111 i = EVP_read_pw_string_min(buf, MIN_LENGTH4, num, prompt, w);
112 if (i != 0) {
113 PEMerror(PEM_R_PROBLEMS_GETTING_PASSWORD)ERR_put_error(9,(0xfff),(109),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,113)
;
114 memset(buf, 0, num);
115 return (-1);
116 }
117 l = strlen(buf);
118 if (l < MIN_LENGTH4) {
119 fprintf(stderr(&__sF[2]), "phrase is too short, "
120 "needs to be at least %zu chars\n",
121 (size_t)MIN_LENGTH4);
122 } else
123 break;
124 }
125 return (int)l;
126}
127LCRYPTO_ALIAS(PEM_def_callback)asm("");
128
129void
130PEM_proc_type(char *buf, int type)
131{
132 const char *str;
133
134 if (type == PEM_TYPE_ENCRYPTED10)
135 str = "ENCRYPTED";
136 else if (type == PEM_TYPE_MIC_CLEAR30)
137 str = "MIC-CLEAR";
138 else if (type == PEM_TYPE_MIC_ONLY20)
139 str = "MIC-ONLY";
140 else
141 str = "BAD-TYPE";
142
143 strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE1024);
144 strlcat(buf, str, PEM_BUFSIZE1024);
145 strlcat(buf, "\n", PEM_BUFSIZE1024);
146}
147LCRYPTO_ALIAS(PEM_proc_type)asm("");
148
149void
150PEM_dek_info(char *buf, const char *type, int len, char *str)
151{
152 static const unsigned char map[17] = "0123456789ABCDEF";
153 long i;
154 int j;
155
156 strlcat(buf, "DEK-Info: ", PEM_BUFSIZE1024);
157 strlcat(buf, type, PEM_BUFSIZE1024);
158 strlcat(buf, ",", PEM_BUFSIZE1024);
159 j = strlen(buf);
160 if (j + (len * 2) + 1 > PEM_BUFSIZE1024)
161 return;
162 for (i = 0; i < len; i++) {
163 buf[j + i * 2] = map[(str[i] >> 4) & 0x0f];
164 buf[j + i * 2 + 1] = map[(str[i]) & 0x0f];
165 }
166 buf[j + i * 2] = '\n';
167 buf[j + i * 2 + 1] = '\0';
168}
169LCRYPTO_ALIAS(PEM_dek_info)asm("");
170
171void *
172PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
173 pem_password_cb *cb, void *u)
174{
175 BIO *b;
176 void *ret;
177
178 if ((b = BIO_new(BIO_s_file())) == NULL((void *)0)) {
179 PEMerror(ERR_R_BUF_LIB)ERR_put_error(9,(0xfff),(7),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,179)
;
180 return (0);
181 }
182 BIO_set_fp(b, fp, BIO_NOCLOSE)BIO_ctrl(b,106,0x00,(char *)fp);
183 ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u);
184 BIO_free(b);
185 return (ret);
186}
187LCRYPTO_ALIAS(PEM_ASN1_read)asm("");
188
189static int
190check_pem(const char *nm, const char *name)
191{
192 /* Normal matching nm and name */
193 if (!strcmp(nm, name))
194 return 1;
195
196 /* Make PEM_STRING_EVP_PKEY match any private key */
197
198 if (!strcmp(name, PEM_STRING_EVP_PKEY"ANY PRIVATE KEY")) {
199 int slen;
200 const EVP_PKEY_ASN1_METHOD *ameth;
201 if (!strcmp(nm, PEM_STRING_PKCS8"ENCRYPTED PRIVATE KEY"))
202 return 1;
203 if (!strcmp(nm, PEM_STRING_PKCS8INF"PRIVATE KEY"))
204 return 1;
205 slen = pem_check_suffix(nm, "PRIVATE KEY");
206 if (slen > 0) {
207 /* NB: ENGINE implementations wont contain
208 * a deprecated old private key decode function
209 * so don't look for them.
210 */
211 ameth = EVP_PKEY_asn1_find_str(NULL((void *)0), nm, slen);
212 if (ameth && ameth->old_priv_decode)
213 return 1;
214 }
215 return 0;
216 }
217
218 if (!strcmp(name, PEM_STRING_PARAMETERS"PARAMETERS")) {
219 int slen;
220 const EVP_PKEY_ASN1_METHOD *ameth;
221 slen = pem_check_suffix(nm, "PARAMETERS");
222 if (slen > 0) {
223 ameth = EVP_PKEY_asn1_find_str(NULL((void *)0), nm, slen);
224 if (ameth) {
225 int r;
226 if (ameth->param_decode)
227 r = 1;
228 else
229 r = 0;
230 return r;
231 }
232 }
233 return 0;
234 }
235
236 /* Permit older strings */
237
238 if (!strcmp(nm, PEM_STRING_X509_OLD"X509 CERTIFICATE") &&
239 !strcmp(name, PEM_STRING_X509"CERTIFICATE"))
240 return 1;
241
242 if (!strcmp(nm, PEM_STRING_X509_REQ_OLD"NEW CERTIFICATE REQUEST") &&
243 !strcmp(name, PEM_STRING_X509_REQ"CERTIFICATE REQUEST"))
244 return 1;
245
246 /* Allow normal certs to be read as trusted certs */
247 if (!strcmp(nm, PEM_STRING_X509"CERTIFICATE") &&
248 !strcmp(name, PEM_STRING_X509_TRUSTED"TRUSTED CERTIFICATE"))
249 return 1;
250
251 if (!strcmp(nm, PEM_STRING_X509_OLD"X509 CERTIFICATE") &&
252 !strcmp(name, PEM_STRING_X509_TRUSTED"TRUSTED CERTIFICATE"))
253 return 1;
254
255 /* Some CAs use PKCS#7 with CERTIFICATE headers */
256 if (!strcmp(nm, PEM_STRING_X509"CERTIFICATE") &&
257 !strcmp(name, PEM_STRING_PKCS7"PKCS7"))
258 return 1;
259
260 if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED"PKCS #7 SIGNED DATA") &&
261 !strcmp(name, PEM_STRING_PKCS7"PKCS7"))
262 return 1;
263
264#ifndef OPENSSL_NO_CMS
265 if (strcmp(nm, PEM_STRING_X509"CERTIFICATE") == 0 &&
266 strcmp(name, PEM_STRING_CMS"CMS") == 0)
267 return 1;
268
269 /* Allow CMS to be read from PKCS#7 headers */
270 if (strcmp(nm, PEM_STRING_PKCS7"PKCS7") == 0 &&
271 strcmp(name, PEM_STRING_CMS"CMS") == 0)
272 return 1;
273#endif
274
275 return 0;
276}
277
278int
279PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm,
280 const char *name, BIO *bp, pem_password_cb *cb, void *u)
281{
282 EVP_CIPHER_INFO cipher;
283 char *nm = NULL((void *)0), *header = NULL((void *)0);
284 unsigned char *data = NULL((void *)0);
285 long len;
286 int ret = 0;
287
288 for (;;) {
1
Loop condition is true. Entering loop body
289 if (!PEM_read_bio(bp, &nm, &header, &data, &len)) {
2
Assuming the condition is false
3
Taking false branch
290 if (ERR_GET_REASON(ERR_peek_error())(int)((ERR_peek_error())&0xfffL) ==
291 PEM_R_NO_START_LINE108)
292 ERR_asprintf_error_data("Expecting: %s", name);
293 return 0;
294 }
295 if (check_pem(nm, name))
4
Taking true branch
296 break;
297 free(nm);
298 free(header);
299 free(data);
300 }
301 if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
5
Execution continues on line 301
6
Calling 'PEM_get_EVP_CIPHER_INFO'
302 goto err;
303 if (!PEM_do_header(&cipher, data, &len, cb, u))
304 goto err;
305
306 *pdata = data;
307 *plen = len;
308
309 if (pnm)
310 *pnm = nm;
311
312 ret = 1;
313
314err:
315 if (!ret || !pnm)
316 free(nm);
317 free(header);
318 if (!ret)
319 free(data);
320 return ret;
321}
322LCRYPTO_ALIAS(PEM_bytes_read_bio)asm("");
323
324int
325PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, void *x,
326 const EVP_CIPHER *enc, unsigned char *kstr, int klen,
327 pem_password_cb *callback, void *u)
328{
329 BIO *b;
330 int ret;
331
332 if ((b = BIO_new(BIO_s_file())) == NULL((void *)0)) {
333 PEMerror(ERR_R_BUF_LIB)ERR_put_error(9,(0xfff),(7),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,333)
;
334 return (0);
335 }
336 BIO_set_fp(b, fp, BIO_NOCLOSE)BIO_ctrl(b,106,0x00,(char *)fp);
337 ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u);
338 BIO_free(b);
339 return (ret);
340}
341LCRYPTO_ALIAS(PEM_ASN1_write)asm("");
342
343int
344PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x,
345 const EVP_CIPHER *enc, unsigned char *kstr, int klen,
346 pem_password_cb *callback, void *u)
347{
348 EVP_CIPHER_CTX ctx;
349 int dsize = 0, i, j, ret = 0;
350 unsigned char *p, *data = NULL((void *)0);
351 const char *objstr = NULL((void *)0);
352 char buf[PEM_BUFSIZE1024];
353 unsigned char key[EVP_MAX_KEY_LENGTH64];
354 unsigned char iv[EVP_MAX_IV_LENGTH16];
355
356 if (enc != NULL((void *)0)) {
357 objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
358 if (objstr == NULL((void *)0)) {
359 PEMerror(PEM_R_UNSUPPORTED_CIPHER)ERR_put_error(9,(0xfff),(113),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,359)
;
360 goto err;
361 }
362 }
363
364 if ((dsize = i2d(x, NULL((void *)0))) < 0) {
365 PEMerror(ERR_R_ASN1_LIB)ERR_put_error(9,(0xfff),(13),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,365)
;
366 dsize = 0;
367 goto err;
368 }
369 /* dzise + 8 bytes are needed */
370 /* actually it needs the cipher block size extra... */
371 data = malloc(dsize + 20);
372 if (data == NULL((void *)0)) {
373 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,373)
;
374 goto err;
375 }
376 p = data;
377 i = i2d(x, &p);
378
379 if (enc != NULL((void *)0)) {
380 if (kstr == NULL((void *)0)) {
381 if (callback == NULL((void *)0))
382 klen = PEM_def_callback(buf, PEM_BUFSIZE1024, 1, u);
383 else
384 klen = (*callback)(buf, PEM_BUFSIZE1024, 1, u);
385 if (klen <= 0) {
386 PEMerror(PEM_R_READ_KEY)ERR_put_error(9,(0xfff),(111),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,386)
;
387 goto err;
388 }
389 kstr = (unsigned char *)buf;
390 }
391 if ((size_t)enc->iv_len > sizeof(iv)) {
392 PEMerror(EVP_R_IV_TOO_LARGE)ERR_put_error(9,(0xfff),(102),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,392)
;
393 goto err;
394 }
395 arc4random_buf(iv, enc->iv_len); /* Generate a salt */
396 /* The 'iv' is used as the iv and as a salt. It is
397 * NOT taken from the BytesToKey function */
398 if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1,
399 key, NULL((void *)0)))
400 goto err;
401
402 if (kstr == (unsigned char *)buf)
403 explicit_bzero(buf, PEM_BUFSIZE1024);
404
405 if (strlen(objstr) + 23 + 2 * enc->iv_len + 13 > sizeof buf) {
406 PEMerror(ASN1_R_BUFFER_TOO_SMALL)ERR_put_error(9,(0xfff),(107),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,406)
;
407 goto err;
408 }
409
410 buf[0] = '\0';
411 PEM_proc_type(buf, PEM_TYPE_ENCRYPTED10);
412 PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv);
413 /* k=strlen(buf); */
414
415 EVP_CIPHER_CTX_init(&ctx);
416 ret = 1;
417 if (!EVP_EncryptInit_ex(&ctx, enc, NULL((void *)0), key, iv) ||
418 !EVP_EncryptUpdate(&ctx, data, &j, data, i) ||
419 !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i))
420 ret = 0;
421 EVP_CIPHER_CTX_cleanup(&ctx);
422 if (ret == 0)
423 goto err;
424 i += j;
425 } else {
426 ret = 1;
427 buf[0] = '\0';
428 }
429 i = PEM_write_bio(bp, name, buf, data, i);
430 if (i <= 0)
431 ret = 0;
432err:
433 explicit_bzero(key, sizeof(key));
434 explicit_bzero(iv, sizeof(iv));
435 explicit_bzero((char *)&ctx, sizeof(ctx));
436 explicit_bzero(buf, PEM_BUFSIZE1024);
437 freezero(data, (unsigned int)dsize);
438 return (ret);
439}
440LCRYPTO_ALIAS(PEM_ASN1_write_bio)asm("");
441
442int
443PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
444 pem_password_cb *callback, void *u)
445{
446 int i, j, o, klen;
447 long len;
448 EVP_CIPHER_CTX ctx;
449 unsigned char key[EVP_MAX_KEY_LENGTH64];
450 char buf[PEM_BUFSIZE1024];
451
452 len = *plen;
453
454 if (cipher->cipher == NULL((void *)0))
455 return (1);
456 if (callback == NULL((void *)0))
457 klen = PEM_def_callback(buf, PEM_BUFSIZE1024, 0, u);
458 else
459 klen = callback(buf, PEM_BUFSIZE1024, 0, u);
460 if (klen <= 0) {
461 PEMerror(PEM_R_BAD_PASSWORD_READ)ERR_put_error(9,(0xfff),(104),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,461)
;
462 return (0);
463 }
464 if (!EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]),
465 (unsigned char *)buf, klen, 1, key, NULL((void *)0)))
466 return 0;
467
468 j = (int)len;
469 EVP_CIPHER_CTX_init(&ctx);
470 o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL((void *)0), key,
471 &(cipher->iv[0]));
472 if (o)
473 o = EVP_DecryptUpdate(&ctx, data, &i, data, j);
474 if (o)
475 o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j);
476 EVP_CIPHER_CTX_cleanup(&ctx);
477 explicit_bzero((char *)buf, sizeof(buf));
478 explicit_bzero((char *)key, sizeof(key));
479 if (!o) {
480 PEMerror(PEM_R_BAD_DECRYPT)ERR_put_error(9,(0xfff),(101),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,480)
;
481 return (0);
482 }
483 *plen = j + i;
484 return (1);
485}
486LCRYPTO_ALIAS(PEM_do_header)asm("");
487
488int
489PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
490{
491 const EVP_CIPHER *enc = NULL((void *)0);
492 char *p, c;
493 char **header_pp = &header;
494
495 cipher->cipher = NULL((void *)0);
496 if ((header == NULL((void *)0)) || (*header == '\0') || (*header == '\n'))
7
Assuming 'header' is not equal to NULL
8
Assuming the condition is false
9
Assuming the condition is false
10
Taking false branch
497 return (1);
498 if (strncmp(header, "Proc-Type: ", 11) != 0) {
11
Taking false branch
499 PEMerror(PEM_R_NOT_PROC_TYPE)ERR_put_error(9,(0xfff),(107),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,499)
;
500 return (0);
501 }
502 header += 11;
503 if (*header != '4')
12
Assuming the condition is false
13
Taking false branch
504 return (0);
505 header++;
506 if (*header != ',')
14
Assuming the condition is false
15
Taking false branch
507 return (0);
508 header++;
509 if (strncmp(header, "ENCRYPTED", 9) != 0) {
510 PEMerror(PEM_R_NOT_ENCRYPTED)ERR_put_error(9,(0xfff),(106),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,510)
;
511 return (0);
512 }
513 for (; (*header != '\n') && (*header != '\0'); header++)
16
Assuming the condition is false
514 ;
515 if (*header == '\0') {
17
Taking false branch
516 PEMerror(PEM_R_SHORT_HEADER)ERR_put_error(9,(0xfff),(112),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,516)
;
517 return (0);
518 }
519 header++;
520 if (strncmp(header, "DEK-Info: ", 10) != 0) {
18
Taking false branch
521 PEMerror(PEM_R_NOT_DEK_INFO)ERR_put_error(9,(0xfff),(105),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,521)
;
522 return (0);
523 }
524 header += 10;
525
526 p = header;
527 for (;;) {
19
Loop condition is true. Entering loop body
528 c= *header;
529 if (!( ((c >= 'A') && (c <= 'Z')) || (c == '-') ||
20
Assuming the condition is false
21
Assuming the condition is false
23
Taking true branch
530 ((c >= '0') && (c <= '9'))))
22
Assuming the condition is false
531 break;
532 header++;
533 }
534 *header = '\0';
24
Execution continues on line 534
535 cipher->cipher = enc = EVP_get_cipherbyname(p);
536 *header = c;
537 header++;
538
539 if (enc == NULL((void *)0)) {
25
Assuming 'enc' is not equal to NULL
26
Taking false branch
540 PEMerror(PEM_R_UNSUPPORTED_ENCRYPTION)ERR_put_error(9,(0xfff),(114),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,540)
;
541 return (0);
542 }
543 if (!load_iv(header_pp, &(cipher->iv[0]), enc->iv_len))
27
Calling 'load_iv'
544 return (0);
545
546 return (1);
547}
548LCRYPTO_ALIAS(PEM_get_EVP_CIPHER_INFO)asm("");
549
550static int
551load_iv(char **fromp, unsigned char *to, int num)
552{
553 int v, i;
554 char *from;
555
556 from= *fromp;
557 for (i = 0; i < num; i++)
28
Assuming 'i' is >= 'num'
29
Loop condition is false. Execution continues on line 559
558 to[i] = 0;
559 num *= 2;
560 for (i = 0; i < num; i++) {
30
The value 0 is assigned to 'i'
31
Assuming 'i' is < 'num'
561 if ((*from >= '0') && (*from <= '9'))
32
Assuming the condition is true
33
Assuming the condition is true
34
Taking true branch
562 v = *from - '0';
563 else if ((*from >= 'A') && (*from <= 'F'))
564 v = *from - 'A' + 10;
565 else if ((*from >= 'a') && (*from <= 'f'))
566 v = *from - 'a' + 10;
567 else {
568 PEMerror(PEM_R_BAD_IV_CHARS)ERR_put_error(9,(0xfff),(103),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,568)
;
569 return (0);
570 }
571 from++;
572 to[i / 2] |= v << (long)((!(i & 1)) * 4);
35
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage
573 }
574
575 *fromp = from;
576 return (1);
577}
578
579int
580PEM_write(FILE *fp, const char *name, const char *header,
581 const unsigned char *data, long len)
582{
583 BIO *b;
584 int ret;
585
586 if ((b = BIO_new(BIO_s_file())) == NULL((void *)0)) {
587 PEMerror(ERR_R_BUF_LIB)ERR_put_error(9,(0xfff),(7),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,587)
;
588 return (0);
589 }
590 BIO_set_fp(b, fp, BIO_NOCLOSE)BIO_ctrl(b,106,0x00,(char *)fp);
591 ret = PEM_write_bio(b, name, header, data, len);
592 BIO_free(b);
593 return (ret);
594}
595LCRYPTO_ALIAS(PEM_write)asm("");
596
597int
598PEM_write_bio(BIO *bp, const char *name, const char *header,
599 const unsigned char *data, long len)
600{
601 int nlen, n, i, j, outl;
602 unsigned char *buf = NULL((void *)0);
603 EVP_ENCODE_CTX ctx;
604 int reason = ERR_R_BUF_LIB7;
605
606 EVP_EncodeInit(&ctx);
607 nlen = strlen(name);
608
609 if ((BIO_write(bp, "-----BEGIN ", 11) != 11) ||
610 (BIO_write(bp, name, nlen) != nlen) ||
611 (BIO_write(bp, "-----\n", 6) != 6))
612 goto err;
613
614 if (header != NULL((void *)0) && (i = strlen(header)) > 0) {
615 if ((BIO_write(bp, header, i) != i) ||
616 (BIO_write(bp, "\n", 1) != 1))
617 goto err;
618 }
619
620 buf = reallocarray(NULL((void *)0), PEM_BUFSIZE1024, 8);
621 if (buf == NULL((void *)0)) {
622 reason = ERR_R_MALLOC_FAILURE(1|64);
623 goto err;
624 }
625
626 i = j = 0;
627 while (len > 0) {
628 n = (int)((len > (PEM_BUFSIZE1024 * 5)) ? (PEM_BUFSIZE1024 * 5) : len);
629 if (!EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n))
630 goto err;
631 if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl))
632 goto err;
633 i += outl;
634 len -= n;
635 j += n;
636 }
637 EVP_EncodeFinal(&ctx, buf, &outl);
638 if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl))
639 goto err;
640 freezero(buf, PEM_BUFSIZE1024 * 8);
641 buf = NULL((void *)0);
642 if ((BIO_write(bp, "-----END ", 9) != 9) ||
643 (BIO_write(bp, name, nlen) != nlen) ||
644 (BIO_write(bp, "-----\n", 6) != 6))
645 goto err;
646 return (i + outl);
647
648err:
649 freezero(buf, PEM_BUFSIZE1024 * 8);
650 PEMerror(reason)ERR_put_error(9,(0xfff),(reason),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,650)
;
651 return (0);
652}
653LCRYPTO_ALIAS(PEM_write_bio)asm("");
654
655int
656PEM_read(FILE *fp, char **name, char **header, unsigned char **data, long *len)
657{
658 BIO *b;
659 int ret;
660
661 if ((b = BIO_new(BIO_s_file())) == NULL((void *)0)) {
662 PEMerror(ERR_R_BUF_LIB)ERR_put_error(9,(0xfff),(7),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,662)
;
663 return (0);
664 }
665 BIO_set_fp(b, fp, BIO_NOCLOSE)BIO_ctrl(b,106,0x00,(char *)fp);
666 ret = PEM_read_bio(b, name, header, data, len);
667 BIO_free(b);
668 return (ret);
669}
670LCRYPTO_ALIAS(PEM_read)asm("");
671
672int
673PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
674 long *len)
675{
676 EVP_ENCODE_CTX ctx;
677 int end = 0, i, k, bl = 0, hl = 0, nohead = 0;
678 char buf[256];
679 BUF_MEM *nameB;
680 BUF_MEM *headerB;
681 BUF_MEM *dataB, *tmpB;
682
683 nameB = BUF_MEM_new();
684 headerB = BUF_MEM_new();
685 dataB = BUF_MEM_new();
686 if ((nameB == NULL((void *)0)) || (headerB == NULL((void *)0)) || (dataB == NULL((void *)0))) {
687 BUF_MEM_free(nameB);
688 BUF_MEM_free(headerB);
689 BUF_MEM_free(dataB);
690 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,690)
;
691 return (0);
692 }
693
694 buf[254] = '\0';
695 for (;;) {
696 i = BIO_gets(bp, buf, 254);
697
698 if (i <= 0) {
699 PEMerror(PEM_R_NO_START_LINE)ERR_put_error(9,(0xfff),(108),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,699)
;
700 goto err;
701 }
702
703 while ((i >= 0) && (buf[i] <= ' '))
704 i--;
705 buf[++i] = '\n';
706 buf[++i] = '\0';
707
708 if (strncmp(buf, "-----BEGIN ", 11) == 0) {
709 i = strlen(&(buf[11]));
710
711 if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0)
712 continue;
713 if (!BUF_MEM_grow(nameB, i + 9)) {
714 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,714)
;
715 goto err;
716 }
717 memcpy(nameB->data, &(buf[11]), i - 6);
718 nameB->data[i - 6] = '\0';
719 break;
720 }
721 }
722 hl = 0;
723 if (!BUF_MEM_grow(headerB, 256)) {
724 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,724)
;
725 goto err;
726 }
727 headerB->data[0] = '\0';
728 for (;;) {
729 i = BIO_gets(bp, buf, 254);
730 if (i <= 0)
731 break;
732
733 while ((i >= 0) && (buf[i] <= ' '))
734 i--;
735 buf[++i] = '\n';
736 buf[++i] = '\0';
737
738 if (buf[0] == '\n')
739 break;
740 if (!BUF_MEM_grow(headerB, hl + i + 9)) {
741 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,741)
;
742 goto err;
743 }
744 if (strncmp(buf, "-----END ", 9) == 0) {
745 nohead = 1;
746 break;
747 }
748 memcpy(&(headerB->data[hl]), buf, i);
749 headerB->data[hl + i] = '\0';
750 hl += i;
751 }
752
753 bl = 0;
754 if (!BUF_MEM_grow(dataB, 1024)) {
755 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,755)
;
756 goto err;
757 }
758 dataB->data[0] = '\0';
759 if (!nohead) {
760 for (;;) {
761 i = BIO_gets(bp, buf, 254);
762 if (i <= 0)
763 break;
764
765 while ((i >= 0) && (buf[i] <= ' '))
766 i--;
767 buf[++i] = '\n';
768 buf[++i] = '\0';
769
770 if (i != 65)
771 end = 1;
772 if (strncmp(buf, "-----END ", 9) == 0)
773 break;
774 if (i > 65)
775 break;
776 if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) {
777 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,777)
;
778 goto err;
779 }
780 memcpy(&(dataB->data[bl]), buf, i);
781 dataB->data[bl + i] = '\0';
782 bl += i;
783 if (end) {
784 buf[0] = '\0';
785 i = BIO_gets(bp, buf, 254);
786 if (i <= 0)
787 break;
788
789 while ((i >= 0) && (buf[i] <= ' '))
790 i--;
791 buf[++i] = '\n';
792 buf[++i] = '\0';
793
794 break;
795 }
796 }
797 } else {
798 tmpB = headerB;
799 headerB = dataB;
800 dataB = tmpB;
801 bl = hl;
802 }
803 i = strlen(nameB->data);
804 if ((strncmp(buf, "-----END ", 9) != 0) ||
805 (strncmp(nameB->data, &(buf[9]), i) != 0) ||
806 (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) {
807 PEMerror(PEM_R_BAD_END_LINE)ERR_put_error(9,(0xfff),(102),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,807)
;
808 goto err;
809 }
810
811 EVP_DecodeInit(&ctx);
812 i = EVP_DecodeUpdate(&ctx,
813 (unsigned char *)dataB->data, &bl,
814 (unsigned char *)dataB->data, bl);
815 if (i < 0) {
816 PEMerror(PEM_R_BAD_BASE64_DECODE)ERR_put_error(9,(0xfff),(100),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,816)
;
817 goto err;
818 }
819 i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k);
820 if (i < 0) {
821 PEMerror(PEM_R_BAD_BASE64_DECODE)ERR_put_error(9,(0xfff),(100),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,821)
;
822 goto err;
823 }
824 bl += k;
825
826 if (bl == 0)
827 goto err;
828 *name = nameB->data;
829 *header = headerB->data;
830 *data = (unsigned char *)dataB->data;
831 *len = bl;
832 free(nameB);
833 free(headerB);
834 free(dataB);
835 return (1);
836
837err:
838 BUF_MEM_free(nameB);
839 BUF_MEM_free(headerB);
840 BUF_MEM_free(dataB);
841 return (0);
842}
843LCRYPTO_ALIAS(PEM_read_bio)asm("");
844
845/* Check pem string and return prefix length.
846 * If for example the pem_str == "RSA PRIVATE KEY" and suffix = "PRIVATE KEY"
847 * the return value is 3 for the string "RSA".
848 */
849
850int
851pem_check_suffix(const char *pem_str, const char *suffix)
852{
853 int pem_len = strlen(pem_str);
854 int suffix_len = strlen(suffix);
855 const char *p;
856
857 if (suffix_len + 1 >= pem_len)
858 return 0;
859 p = pem_str + pem_len - suffix_len;
860 if (strcmp(p, suffix))
861 return 0;
862 p--;
863 if (*p != ' ')
864 return 0;
865 return p - pem_str;
866}