Coverage Report

Created: 2023-06-08 06:41

/src/openssl111/crypto/pem/pem_pk8.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1995-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 <stdio.h>
11
#include "internal/cryptlib.h"
12
#include <openssl/buffer.h>
13
#include <openssl/objects.h>
14
#include <openssl/evp.h>
15
#include <openssl/x509.h>
16
#include <openssl/pkcs12.h>
17
#include <openssl/pem.h>
18
19
static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder,
20
                      int nid, const EVP_CIPHER *enc,
21
                      char *kstr, int klen, pem_password_cb *cb, void *u);
22
23
#ifndef OPENSSL_NO_STDIO
24
static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder,
25
                         int nid, const EVP_CIPHER *enc,
26
                         char *kstr, int klen, pem_password_cb *cb, void *u);
27
#endif
28
/*
29
 * These functions write a private key in PKCS#8 format: it is a "drop in"
30
 * replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc'
31
 * is NULL then it uses the unencrypted private key form. The 'nid' versions
32
 * uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0.
33
 */
34
35
int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
36
                                      char *kstr, int klen,
37
                                      pem_password_cb *cb, void *u)
38
0
{
39
0
    return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u);
40
0
}
41
42
int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
43
                                  char *kstr, int klen,
44
                                  pem_password_cb *cb, void *u)
45
0
{
46
0
    return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u);
47
0
}
48
49
int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
50
                            char *kstr, int klen,
51
                            pem_password_cb *cb, void *u)
52
0
{
53
0
    return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u);
54
0
}
55
56
int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
57
                                char *kstr, int klen,
58
                                pem_password_cb *cb, void *u)
59
0
{
60
0
    return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u);
61
0
}
62
63
static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid,
64
                      const EVP_CIPHER *enc, char *kstr, int klen,
65
                      pem_password_cb *cb, void *u)
66
0
{
67
0
    X509_SIG *p8;
68
0
    PKCS8_PRIV_KEY_INFO *p8inf;
69
0
    char buf[PEM_BUFSIZE];
70
0
    int ret;
71
72
0
    if ((p8inf = EVP_PKEY2PKCS8(x)) == NULL) {
73
0
        PEMerr(PEM_F_DO_PK8PKEY, PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
74
0
        return 0;
75
0
    }
76
0
    if (enc || (nid != -1)) {
77
0
        if (!kstr) {
78
0
            if (!cb)
79
0
                klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u);
80
0
            else
81
0
                klen = cb(buf, PEM_BUFSIZE, 1, u);
82
0
            if (klen <= 0) {
83
0
                PEMerr(PEM_F_DO_PK8PKEY, PEM_R_READ_KEY);
84
0
                PKCS8_PRIV_KEY_INFO_free(p8inf);
85
0
                return 0;
86
0
            }
87
88
0
            kstr = buf;
89
0
        }
90
0
        p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf);
91
0
        if (kstr == buf)
92
0
            OPENSSL_cleanse(buf, klen);
93
0
        PKCS8_PRIV_KEY_INFO_free(p8inf);
94
0
        if (p8 == NULL)
95
0
            return 0;
96
0
        if (isder)
97
0
            ret = i2d_PKCS8_bio(bp, p8);
98
0
        else
99
0
            ret = PEM_write_bio_PKCS8(bp, p8);
100
0
        X509_SIG_free(p8);
101
0
        return ret;
102
0
    } else {
103
0
        if (isder)
104
0
            ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
105
0
        else
106
0
            ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
107
0
        PKCS8_PRIV_KEY_INFO_free(p8inf);
108
0
        return ret;
109
0
    }
110
0
}
111
112
EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
113
                                  void *u)
114
0
{
115
0
    PKCS8_PRIV_KEY_INFO *p8inf = NULL;
116
0
    X509_SIG *p8 = NULL;
117
0
    int klen;
118
0
    EVP_PKEY *ret;
119
0
    char psbuf[PEM_BUFSIZE];
120
0
    p8 = d2i_PKCS8_bio(bp, NULL);
121
0
    if (!p8)
122
0
        return NULL;
123
0
    if (cb)
124
0
        klen = cb(psbuf, PEM_BUFSIZE, 0, u);
125
0
    else
126
0
        klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
127
0
    if (klen < 0) {
128
0
        PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ);
129
0
        X509_SIG_free(p8);
130
0
        return NULL;
131
0
    }
132
0
    p8inf = PKCS8_decrypt(p8, psbuf, klen);
133
0
    X509_SIG_free(p8);
134
0
    OPENSSL_cleanse(psbuf, klen);
135
0
    if (!p8inf)
136
0
        return NULL;
137
0
    ret = EVP_PKCS82PKEY(p8inf);
138
0
    PKCS8_PRIV_KEY_INFO_free(p8inf);
139
0
    if (!ret)
140
0
        return NULL;
141
0
    if (x) {
142
0
        EVP_PKEY_free(*x);
143
0
        *x = ret;
144
0
    }
145
0
    return ret;
146
0
}
147
148
#ifndef OPENSSL_NO_STDIO
149
150
int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
151
                           char *kstr, int klen, pem_password_cb *cb, void *u)
152
0
{
153
0
    return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u);
154
0
}
155
156
int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid,
157
                               char *kstr, int klen,
158
                               pem_password_cb *cb, void *u)
159
0
{
160
0
    return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u);
161
0
}
162
163
int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
164
                                  char *kstr, int klen,
165
                                  pem_password_cb *cb, void *u)
166
0
{
167
0
    return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u);
168
0
}
169
170
int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
171
                              char *kstr, int klen, pem_password_cb *cb,
172
                              void *u)
173
0
{
174
0
    return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u);
175
0
}
176
177
static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid,
178
                         const EVP_CIPHER *enc, char *kstr, int klen,
179
                         pem_password_cb *cb, void *u)
180
0
{
181
0
    BIO *bp;
182
0
    int ret;
183
184
0
    if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
185
0
        PEMerr(PEM_F_DO_PK8PKEY_FP, ERR_R_BUF_LIB);
186
0
        return 0;
187
0
    }
188
0
    ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u);
189
0
    BIO_free(bp);
190
0
    return ret;
191
0
}
192
193
EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
194
                                 void *u)
195
0
{
196
0
    BIO *bp;
197
0
    EVP_PKEY *ret;
198
199
0
    if ((bp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
200
0
        PEMerr(PEM_F_D2I_PKCS8PRIVATEKEY_FP, ERR_R_BUF_LIB);
201
0
        return NULL;
202
0
    }
203
0
    ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u);
204
0
    BIO_free(bp);
205
0
    return ret;
206
0
}
207
208
#endif
209
210
IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG)
211
212
213
IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF,
214
             PKCS8_PRIV_KEY_INFO)