Bug Summary

File:src/lib/libcrypto/pem/pem_lib.c
Warning:line 570, 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.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pem_lib.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/lib/clang/13.0.0 -D LIBRESSL_INTERNAL -D LIBRESSL_CRYPTO_INTERNAL -D DSO_DLFCN -D HAVE_DLFCN_H -D HAVE_FUNOPEN -D OPENSSL_NO_HW_PADLOCK -I /usr/src/lib/libcrypto -I /usr/src/lib/libcrypto/asn1 -I /usr/src/lib/libcrypto/bio -I /usr/src/lib/libcrypto/bn -I /usr/src/lib/libcrypto/bytestring -I /usr/src/lib/libcrypto/dh -I /usr/src/lib/libcrypto/dsa -I /usr/src/lib/libcrypto/ec -I /usr/src/lib/libcrypto/ecdh -I /usr/src/lib/libcrypto/ecdsa -I /usr/src/lib/libcrypto/evp -I /usr/src/lib/libcrypto/hmac -I /usr/src/lib/libcrypto/modes -I /usr/src/lib/libcrypto/ocsp -I /usr/src/lib/libcrypto/rsa -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 OPENSSL_BN_ASM_GF2m -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/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcrypto/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/lib/libcrypto/pem/pem_lib.c
1/* $OpenBSD: pem_lib.c,v 1.50 2021/12/12 21:30:14 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#ifndef OPENSSL_NO_ENGINE
78#include <openssl/engine.h>
79#endif
80
81#include "asn1_locl.h"
82#include "evp_locl.h"
83
84#define MIN_LENGTH4 4
85
86static int load_iv(char **fromp, unsigned char *to, int num);
87static int check_pem(const char *nm, const char *name);
88int pem_check_suffix(const char *pem_str, const char *suffix);
89
90/* XXX LSSL ABI XXX return value and `num' ought to be size_t */
91int
92PEM_def_callback(char *buf, int num, int w, void *key)
93{
94 size_t l;
95 int i;
96 const char *prompt;
97
98 if (num < 0)
99 return -1;
100
101 if (key) {
102 l = strlen(key);
103 if (l > (size_t)num)
104 l = (size_t)num;
105 memcpy(buf, key, l);
106 return (int)l;
107 }
108
109 prompt = EVP_get_pw_prompt();
110 if (prompt == NULL((void*)0))
111 prompt = "Enter PEM pass phrase:";
112
113 for (;;) {
114 i = EVP_read_pw_string_min(buf, MIN_LENGTH4, num, prompt, w);
115 if (i != 0) {
116 PEMerror(PEM_R_PROBLEMS_GETTING_PASSWORD)ERR_put_error(9,(0xfff),(109),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,116)
;
117 memset(buf, 0, num);
118 return (-1);
119 }
120 l = strlen(buf);
121 if (l < MIN_LENGTH4) {
122 fprintf(stderr(&__sF[2]), "phrase is too short, "
123 "needs to be at least %zu chars\n",
124 (size_t)MIN_LENGTH4);
125 } else
126 break;
127 }
128 return (int)l;
129}
130
131void
132PEM_proc_type(char *buf, int type)
133{
134 const char *str;
135
136 if (type == PEM_TYPE_ENCRYPTED10)
137 str = "ENCRYPTED";
138 else if (type == PEM_TYPE_MIC_CLEAR30)
139 str = "MIC-CLEAR";
140 else if (type == PEM_TYPE_MIC_ONLY20)
141 str = "MIC-ONLY";
142 else
143 str = "BAD-TYPE";
144
145 strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE1024);
146 strlcat(buf, str, PEM_BUFSIZE1024);
147 strlcat(buf, "\n", PEM_BUFSIZE1024);
148}
149
150void
151PEM_dek_info(char *buf, const char *type, int len, char *str)
152{
153 static const unsigned char map[17] = "0123456789ABCDEF";
154 long i;
155 int j;
156
157 strlcat(buf, "DEK-Info: ", PEM_BUFSIZE1024);
158 strlcat(buf, type, PEM_BUFSIZE1024);
159 strlcat(buf, ",", PEM_BUFSIZE1024);
160 j = strlen(buf);
161 if (j + (len * 2) + 1 > PEM_BUFSIZE1024)
162 return;
163 for (i = 0; i < len; i++) {
164 buf[j + i * 2] = map[(str[i] >> 4) & 0x0f];
165 buf[j + i * 2 + 1] = map[(str[i]) & 0x0f];
166 }
167 buf[j + i * 2] = '\n';
168 buf[j + i * 2 + 1] = '\0';
169}
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}
187
188static int
189check_pem(const char *nm, const char *name)
190{
191 /* Normal matching nm and name */
192 if (!strcmp(nm, name))
193 return 1;
194
195 /* Make PEM_STRING_EVP_PKEY match any private key */
196
197 if (!strcmp(name, PEM_STRING_EVP_PKEY"ANY PRIVATE KEY")) {
198 int slen;
199 const EVP_PKEY_ASN1_METHOD *ameth;
200 if (!strcmp(nm, PEM_STRING_PKCS8"ENCRYPTED PRIVATE KEY"))
201 return 1;
202 if (!strcmp(nm, PEM_STRING_PKCS8INF"PRIVATE KEY"))
203 return 1;
204 slen = pem_check_suffix(nm, "PRIVATE KEY");
205 if (slen > 0) {
206 /* NB: ENGINE implementations wont contain
207 * a deprecated old private key decode function
208 * so don't look for them.
209 */
210 ameth = EVP_PKEY_asn1_find_str(NULL((void*)0), nm, slen);
211 if (ameth && ameth->old_priv_decode)
212 return 1;
213 }
214 return 0;
215 }
216
217 if (!strcmp(name, PEM_STRING_PARAMETERS"PARAMETERS")) {
218 int slen;
219 const EVP_PKEY_ASN1_METHOD *ameth;
220 slen = pem_check_suffix(nm, "PARAMETERS");
221 if (slen > 0) {
222 ENGINE *e;
223 ameth = EVP_PKEY_asn1_find_str(&e, nm, slen);
224 if (ameth) {
225 int r;
226 if (ameth->param_decode)
227 r = 1;
228 else
229 r = 0;
230#ifndef OPENSSL_NO_ENGINE
231 ENGINE_finish(e);
232#endif
233 return r;
234 }
235 }
236 return 0;
237 }
238
239 /* Permit older strings */
240
241 if (!strcmp(nm, PEM_STRING_X509_OLD"X509 CERTIFICATE") &&
242 !strcmp(name, PEM_STRING_X509"CERTIFICATE"))
243 return 1;
244
245 if (!strcmp(nm, PEM_STRING_X509_REQ_OLD"NEW CERTIFICATE REQUEST") &&
246 !strcmp(name, PEM_STRING_X509_REQ"CERTIFICATE REQUEST"))
247 return 1;
248
249 /* Allow normal certs to be read as trusted certs */
250 if (!strcmp(nm, PEM_STRING_X509"CERTIFICATE") &&
251 !strcmp(name, PEM_STRING_X509_TRUSTED"TRUSTED CERTIFICATE"))
252 return 1;
253
254 if (!strcmp(nm, PEM_STRING_X509_OLD"X509 CERTIFICATE") &&
255 !strcmp(name, PEM_STRING_X509_TRUSTED"TRUSTED CERTIFICATE"))
256 return 1;
257
258 /* Some CAs use PKCS#7 with CERTIFICATE headers */
259 if (!strcmp(nm, PEM_STRING_X509"CERTIFICATE") &&
260 !strcmp(name, PEM_STRING_PKCS7"PKCS7"))
261 return 1;
262
263 if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED"PKCS #7 SIGNED DATA") &&
264 !strcmp(name, PEM_STRING_PKCS7"PKCS7"))
265 return 1;
266
267#ifndef OPENSSL_NO_CMS
268 if (strcmp(nm, PEM_STRING_X509"CERTIFICATE") == 0 &&
269 strcmp(name, PEM_STRING_CMS"CMS") == 0)
270 return 1;
271
272 /* Allow CMS to be read from PKCS#7 headers */
273 if (strcmp(nm, PEM_STRING_PKCS7"PKCS7") == 0 &&
274 strcmp(name, PEM_STRING_CMS"CMS") == 0)
275 return 1;
276#endif
277
278 return 0;
279}
280
281int
282PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm,
283 const char *name, BIO *bp, pem_password_cb *cb, void *u)
284{
285 EVP_CIPHER_INFO cipher;
286 char *nm = NULL((void*)0), *header = NULL((void*)0);
287 unsigned char *data = NULL((void*)0);
288 long len;
289 int ret = 0;
290
291 for (;;) {
1
Loop condition is true. Entering loop body
292 if (!PEM_read_bio(bp, &nm, &header, &data, &len)) {
2
Assuming the condition is false
3
Taking false branch
293 if (ERR_GET_REASON(ERR_peek_error())(int)((ERR_peek_error())&0xfffL) ==
294 PEM_R_NO_START_LINE108)
295 ERR_asprintf_error_data("Expecting: %s", name);
296 return 0;
297 }
298 if (check_pem(nm, name))
4
Taking true branch
299 break;
5
Execution continues on line 304
300 free(nm);
301 free(header);
302 free(data);
303 }
304 if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
6
Calling 'PEM_get_EVP_CIPHER_INFO'
305 goto err;
306 if (!PEM_do_header(&cipher, data, &len, cb, u))
307 goto err;
308
309 *pdata = data;
310 *plen = len;
311
312 if (pnm)
313 *pnm = nm;
314
315 ret = 1;
316
317err:
318 if (!ret || !pnm)
319 free(nm);
320 free(header);
321 if (!ret)
322 free(data);
323 return ret;
324}
325
326int
327PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, void *x,
328 const EVP_CIPHER *enc, unsigned char *kstr, int klen,
329 pem_password_cb *callback, void *u)
330{
331 BIO *b;
332 int ret;
333
334 if ((b = BIO_new(BIO_s_file())) == NULL((void*)0)) {
335 PEMerror(ERR_R_BUF_LIB)ERR_put_error(9,(0xfff),(7),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,335)
;
336 return (0);
337 }
338 BIO_set_fp(b, fp, BIO_NOCLOSE)BIO_ctrl(b,106,0x00,(char *)fp);
339 ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u);
340 BIO_free(b);
341 return (ret);
342}
343
344int
345PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x,
346 const EVP_CIPHER *enc, unsigned char *kstr, int klen,
347 pem_password_cb *callback, void *u)
348{
349 EVP_CIPHER_CTX ctx;
350 int dsize = 0, i, j, ret = 0;
351 unsigned char *p, *data = NULL((void*)0);
352 const char *objstr = NULL((void*)0);
353 char buf[PEM_BUFSIZE1024];
354 unsigned char key[EVP_MAX_KEY_LENGTH64];
355 unsigned char iv[EVP_MAX_IV_LENGTH16];
356
357 if (enc != NULL((void*)0)) {
358 objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
359 if (objstr == NULL((void*)0)) {
360 PEMerror(PEM_R_UNSUPPORTED_CIPHER)ERR_put_error(9,(0xfff),(113),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,360)
;
361 goto err;
362 }
363 }
364
365 if ((dsize = i2d(x, NULL((void*)0))) < 0) {
366 PEMerror(ERR_R_ASN1_LIB)ERR_put_error(9,(0xfff),(13),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,366)
;
367 dsize = 0;
368 goto err;
369 }
370 /* dzise + 8 bytes are needed */
371 /* actually it needs the cipher block size extra... */
372 data = malloc(dsize + 20);
373 if (data == NULL((void*)0)) {
374 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,374)
;
375 goto err;
376 }
377 p = data;
378 i = i2d(x, &p);
379
380 if (enc != NULL((void*)0)) {
381 if (kstr == NULL((void*)0)) {
382 if (callback == NULL((void*)0))
383 klen = PEM_def_callback(buf, PEM_BUFSIZE1024, 1, u);
384 else
385 klen = (*callback)(buf, PEM_BUFSIZE1024, 1, u);
386 if (klen <= 0) {
387 PEMerror(PEM_R_READ_KEY)ERR_put_error(9,(0xfff),(111),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,387)
;
388 goto err;
389 }
390 kstr = (unsigned char *)buf;
391 }
392 if ((size_t)enc->iv_len > sizeof(iv)) {
393 PEMerror(EVP_R_IV_TOO_LARGE)ERR_put_error(9,(0xfff),(102),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,393)
;
394 goto err;
395 }
396 arc4random_buf(iv, enc->iv_len); /* Generate a salt */
397 /* The 'iv' is used as the iv and as a salt. It is
398 * NOT taken from the BytesToKey function */
399 if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1,
400 key, NULL((void*)0)))
401 goto err;
402
403 if (kstr == (unsigned char *)buf)
404 explicit_bzero(buf, PEM_BUFSIZE1024);
405
406 if (strlen(objstr) + 23 + 2 * enc->iv_len + 13 > sizeof buf) {
407 PEMerror(ASN1_R_BUFFER_TOO_SMALL)ERR_put_error(9,(0xfff),(107),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,407)
;
408 goto err;
409 }
410
411 buf[0] = '\0';
412 PEM_proc_type(buf, PEM_TYPE_ENCRYPTED10);
413 PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv);
414 /* k=strlen(buf); */
415
416 EVP_CIPHER_CTX_init(&ctx);
417 ret = 1;
418 if (!EVP_EncryptInit_ex(&ctx, enc, NULL((void*)0), key, iv) ||
419 !EVP_EncryptUpdate(&ctx, data, &j, data, i) ||
420 !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i))
421 ret = 0;
422 EVP_CIPHER_CTX_cleanup(&ctx);
423 if (ret == 0)
424 goto err;
425 i += j;
426 } else {
427 ret = 1;
428 buf[0] = '\0';
429 }
430 i = PEM_write_bio(bp, name, buf, data, i);
431 if (i <= 0)
432 ret = 0;
433err:
434 explicit_bzero(key, sizeof(key));
435 explicit_bzero(iv, sizeof(iv));
436 explicit_bzero((char *)&ctx, sizeof(ctx));
437 explicit_bzero(buf, PEM_BUFSIZE1024);
438 freezero(data, (unsigned int)dsize);
439 return (ret);
440}
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}
486
487int
488PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
489{
490 const EVP_CIPHER *enc = NULL((void*)0);
491 char *p, c;
492 char **header_pp = &header;
493
494 cipher->cipher = NULL((void*)0);
495 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
496 return (1);
497 if (strncmp(header, "Proc-Type: ", 11) != 0) {
11
Taking false branch
498 PEMerror(PEM_R_NOT_PROC_TYPE)ERR_put_error(9,(0xfff),(107),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,498)
;
499 return (0);
500 }
501 header += 11;
502 if (*header != '4')
12
Assuming the condition is false
13
Taking false branch
503 return (0);
504 header++;
505 if (*header != ',')
14
Assuming the condition is false
15
Taking false branch
506 return (0);
507 header++;
508 if (strncmp(header, "ENCRYPTED", 9) != 0) {
16
Taking false branch
509 PEMerror(PEM_R_NOT_ENCRYPTED)ERR_put_error(9,(0xfff),(106),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,509)
;
510 return (0);
511 }
512 for (; (*header != '\n') && (*header != '\0'); header++)
17
Assuming the condition is false
513 ;
514 if (*header == '\0') {
18
Taking false branch
515 PEMerror(PEM_R_SHORT_HEADER)ERR_put_error(9,(0xfff),(112),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,515)
;
516 return (0);
517 }
518 header++;
519 if (strncmp(header, "DEK-Info: ", 10) != 0) {
19
Taking false branch
520 PEMerror(PEM_R_NOT_DEK_INFO)ERR_put_error(9,(0xfff),(105),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,520)
;
521 return (0);
522 }
523 header += 10;
524
525 p = header;
526 for (;;) {
20
Loop condition is true. Entering loop body
527 c= *header;
528 if (!( ((c >= 'A') && (c <= 'Z')) || (c == '-') ||
21
Assuming the condition is false
22
Assuming the condition is false
24
Taking true branch
529 ((c >= '0') && (c <= '9'))))
23
Assuming the condition is false
530 break;
25
Execution continues on line 533
531 header++;
532 }
533 *header = '\0';
534 cipher->cipher = enc = EVP_get_cipherbyname(p);
535 *header = c;
536 header++;
537
538 if (enc == NULL((void*)0)) {
26
Assuming 'enc' is not equal to NULL
27
Taking false branch
539 PEMerror(PEM_R_UNSUPPORTED_ENCRYPTION)ERR_put_error(9,(0xfff),(114),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,539)
;
540 return (0);
541 }
542 if (!load_iv(header_pp, &(cipher->iv[0]), enc->iv_len))
28
Calling 'load_iv'
543 return (0);
544
545 return (1);
546}
547
548static int
549load_iv(char **fromp, unsigned char *to, int num)
550{
551 int v, i;
552 char *from;
553
554 from= *fromp;
555 for (i = 0; i < num; i++)
29
Assuming 'i' is >= 'num'
30
Loop condition is false. Execution continues on line 557
556 to[i] = 0;
557 num *= 2;
558 for (i = 0; i < num; i++) {
31
The value 0 is assigned to 'i'
32
Assuming 'i' is < 'num'
33
Loop condition is true. Entering loop body
559 if ((*from >= '0') && (*from <= '9'))
34
Assuming the condition is true
35
Assuming the condition is true
36
Taking true branch
560 v = *from - '0';
561 else if ((*from >= 'A') && (*from <= 'F'))
562 v = *from - 'A' + 10;
563 else if ((*from >= 'a') && (*from <= 'f'))
564 v = *from - 'a' + 10;
565 else {
566 PEMerror(PEM_R_BAD_IV_CHARS)ERR_put_error(9,(0xfff),(103),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,566)
;
567 return (0);
568 }
569 from++;
570 to[i / 2] |= v << (long)((!(i & 1)) * 4);
37
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage
571 }
572
573 *fromp = from;
574 return (1);
575}
576
577int
578PEM_write(FILE *fp, const char *name, const char *header,
579 const unsigned char *data, long len)
580{
581 BIO *b;
582 int ret;
583
584 if ((b = BIO_new(BIO_s_file())) == NULL((void*)0)) {
585 PEMerror(ERR_R_BUF_LIB)ERR_put_error(9,(0xfff),(7),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,585)
;
586 return (0);
587 }
588 BIO_set_fp(b, fp, BIO_NOCLOSE)BIO_ctrl(b,106,0x00,(char *)fp);
589 ret = PEM_write_bio(b, name, header, data, len);
590 BIO_free(b);
591 return (ret);
592}
593
594int
595PEM_write_bio(BIO *bp, const char *name, const char *header,
596 const unsigned char *data, long len)
597{
598 int nlen, n, i, j, outl;
599 unsigned char *buf = NULL((void*)0);
600 EVP_ENCODE_CTX ctx;
601 int reason = ERR_R_BUF_LIB7;
602
603 EVP_EncodeInit(&ctx);
604 nlen = strlen(name);
605
606 if ((BIO_write(bp, "-----BEGIN ", 11) != 11) ||
607 (BIO_write(bp, name, nlen) != nlen) ||
608 (BIO_write(bp, "-----\n", 6) != 6))
609 goto err;
610
611 i = strlen(header);
612 if (i > 0) {
613 if ((BIO_write(bp, header, i) != i) ||
614 (BIO_write(bp, "\n", 1) != 1))
615 goto err;
616 }
617
618 buf = reallocarray(NULL((void*)0), PEM_BUFSIZE1024, 8);
619 if (buf == NULL((void*)0)) {
620 reason = ERR_R_MALLOC_FAILURE(1|64);
621 goto err;
622 }
623
624 i = j = 0;
625 while (len > 0) {
626 n = (int)((len > (PEM_BUFSIZE1024 * 5)) ? (PEM_BUFSIZE1024 * 5) : len);
627 if (!EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n))
628 goto err;
629 if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl))
630 goto err;
631 i += outl;
632 len -= n;
633 j += n;
634 }
635 EVP_EncodeFinal(&ctx, buf, &outl);
636 if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl))
637 goto err;
638 freezero(buf, PEM_BUFSIZE1024 * 8);
639 buf = NULL((void*)0);
640 if ((BIO_write(bp, "-----END ", 9) != 9) ||
641 (BIO_write(bp, name, nlen) != nlen) ||
642 (BIO_write(bp, "-----\n", 6) != 6))
643 goto err;
644 return (i + outl);
645
646err:
647 freezero(buf, PEM_BUFSIZE1024 * 8);
648 PEMerror(reason)ERR_put_error(9,(0xfff),(reason),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,648)
;
649 return (0);
650}
651
652int
653PEM_read(FILE *fp, char **name, char **header, unsigned char **data, long *len)
654{
655 BIO *b;
656 int ret;
657
658 if ((b = BIO_new(BIO_s_file())) == NULL((void*)0)) {
659 PEMerror(ERR_R_BUF_LIB)ERR_put_error(9,(0xfff),(7),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,659)
;
660 return (0);
661 }
662 BIO_set_fp(b, fp, BIO_NOCLOSE)BIO_ctrl(b,106,0x00,(char *)fp);
663 ret = PEM_read_bio(b, name, header, data, len);
664 BIO_free(b);
665 return (ret);
666}
667
668int
669PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
670 long *len)
671{
672 EVP_ENCODE_CTX ctx;
673 int end = 0, i, k, bl = 0, hl = 0, nohead = 0;
674 char buf[256];
675 BUF_MEM *nameB;
676 BUF_MEM *headerB;
677 BUF_MEM *dataB, *tmpB;
678
679 nameB = BUF_MEM_new();
680 headerB = BUF_MEM_new();
681 dataB = BUF_MEM_new();
682 if ((nameB == NULL((void*)0)) || (headerB == NULL((void*)0)) || (dataB == NULL((void*)0))) {
683 BUF_MEM_free(nameB);
684 BUF_MEM_free(headerB);
685 BUF_MEM_free(dataB);
686 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,686)
;
687 return (0);
688 }
689
690 buf[254] = '\0';
691 for (;;) {
692 i = BIO_gets(bp, buf, 254);
693
694 if (i <= 0) {
695 PEMerror(PEM_R_NO_START_LINE)ERR_put_error(9,(0xfff),(108),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,695)
;
696 goto err;
697 }
698
699 while ((i >= 0) && (buf[i] <= ' '))
700 i--;
701 buf[++i] = '\n';
702 buf[++i] = '\0';
703
704 if (strncmp(buf, "-----BEGIN ", 11) == 0) {
705 i = strlen(&(buf[11]));
706
707 if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0)
708 continue;
709 if (!BUF_MEM_grow(nameB, i + 9)) {
710 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,710)
;
711 goto err;
712 }
713 memcpy(nameB->data, &(buf[11]), i - 6);
714 nameB->data[i - 6] = '\0';
715 break;
716 }
717 }
718 hl = 0;
719 if (!BUF_MEM_grow(headerB, 256)) {
720 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,720)
;
721 goto err;
722 }
723 headerB->data[0] = '\0';
724 for (;;) {
725 i = BIO_gets(bp, buf, 254);
726 if (i <= 0)
727 break;
728
729 while ((i >= 0) && (buf[i] <= ' '))
730 i--;
731 buf[++i] = '\n';
732 buf[++i] = '\0';
733
734 if (buf[0] == '\n')
735 break;
736 if (!BUF_MEM_grow(headerB, hl + i + 9)) {
737 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,737)
;
738 goto err;
739 }
740 if (strncmp(buf, "-----END ", 9) == 0) {
741 nohead = 1;
742 break;
743 }
744 memcpy(&(headerB->data[hl]), buf, i);
745 headerB->data[hl + i] = '\0';
746 hl += i;
747 }
748
749 bl = 0;
750 if (!BUF_MEM_grow(dataB, 1024)) {
751 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,751)
;
752 goto err;
753 }
754 dataB->data[0] = '\0';
755 if (!nohead) {
756 for (;;) {
757 i = BIO_gets(bp, buf, 254);
758 if (i <= 0)
759 break;
760
761 while ((i >= 0) && (buf[i] <= ' '))
762 i--;
763 buf[++i] = '\n';
764 buf[++i] = '\0';
765
766 if (i != 65)
767 end = 1;
768 if (strncmp(buf, "-----END ", 9) == 0)
769 break;
770 if (i > 65)
771 break;
772 if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) {
773 PEMerror(ERR_R_MALLOC_FAILURE)ERR_put_error(9,(0xfff),((1|64)),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,773)
;
774 goto err;
775 }
776 memcpy(&(dataB->data[bl]), buf, i);
777 dataB->data[bl + i] = '\0';
778 bl += i;
779 if (end) {
780 buf[0] = '\0';
781 i = BIO_gets(bp, buf, 254);
782 if (i <= 0)
783 break;
784
785 while ((i >= 0) && (buf[i] <= ' '))
786 i--;
787 buf[++i] = '\n';
788 buf[++i] = '\0';
789
790 break;
791 }
792 }
793 } else {
794 tmpB = headerB;
795 headerB = dataB;
796 dataB = tmpB;
797 bl = hl;
798 }
799 i = strlen(nameB->data);
800 if ((strncmp(buf, "-----END ", 9) != 0) ||
801 (strncmp(nameB->data, &(buf[9]), i) != 0) ||
802 (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) {
803 PEMerror(PEM_R_BAD_END_LINE)ERR_put_error(9,(0xfff),(102),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,803)
;
804 goto err;
805 }
806
807 EVP_DecodeInit(&ctx);
808 i = EVP_DecodeUpdate(&ctx,
809 (unsigned char *)dataB->data, &bl,
810 (unsigned char *)dataB->data, bl);
811 if (i < 0) {
812 PEMerror(PEM_R_BAD_BASE64_DECODE)ERR_put_error(9,(0xfff),(100),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,812)
;
813 goto err;
814 }
815 i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k);
816 if (i < 0) {
817 PEMerror(PEM_R_BAD_BASE64_DECODE)ERR_put_error(9,(0xfff),(100),"/usr/src/lib/libcrypto/pem/pem_lib.c"
,817)
;
818 goto err;
819 }
820 bl += k;
821
822 if (bl == 0)
823 goto err;
824 *name = nameB->data;
825 *header = headerB->data;
826 *data = (unsigned char *)dataB->data;
827 *len = bl;
828 free(nameB);
829 free(headerB);
830 free(dataB);
831 return (1);
832
833err:
834 BUF_MEM_free(nameB);
835 BUF_MEM_free(headerB);
836 BUF_MEM_free(dataB);
837 return (0);
838}
839
840/* Check pem string and return prefix length.
841 * If for example the pem_str == "RSA PRIVATE KEY" and suffix = "PRIVATE KEY"
842 * the return value is 3 for the string "RSA".
843 */
844
845int
846pem_check_suffix(const char *pem_str, const char *suffix)
847{
848 int pem_len = strlen(pem_str);
849 int suffix_len = strlen(suffix);
850 const char *p;
851
852 if (suffix_len + 1 >= pem_len)
853 return 0;
854 p = pem_str + pem_len - suffix_len;
855 if (strcmp(p, suffix))
856 return 0;
857 p--;
858 if (*p != ' ')
859 return 0;
860 return p - pem_str;
861}