source: rtems-libbsd/freebsd/crypto/openssl/apps/pkcs8.c @ 0a699e7

5-freebsd-126-freebsd-12
Last change on this file since 0a699e7 was 0a699e7, checked in by Christian Mauderer <christian.mauderer@…>, on 03/28/19 at 06:13:59

bin/openssl: Import from FreeBSD.

  • Property mode set to 100644
File size: 11.3 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
5 *
6 * Licensed under the OpenSSL license (the "License").  You may not use
7 * this file except in compliance with the License.  You can obtain a copy
8 * in the file LICENSE in the source distribution or at
9 * https://www.openssl.org/source/license.html
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include "apps.h"
16#include "progs.h"
17#include <openssl/pem.h>
18#include <openssl/err.h>
19#include <openssl/evp.h>
20#include <openssl/pkcs12.h>
21
22typedef enum OPTION_choice {
23    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
24    OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
25    OPT_TOPK8, OPT_NOITER, OPT_NOCRYPT,
26#ifndef OPENSSL_NO_SCRYPT
27    OPT_SCRYPT, OPT_SCRYPT_N, OPT_SCRYPT_R, OPT_SCRYPT_P,
28#endif
29    OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT,
30    OPT_TRADITIONAL,
31    OPT_R_ENUM
32} OPTION_CHOICE;
33
34const OPTIONS pkcs8_options[] = {
35    {"help", OPT_HELP, '-', "Display this summary"},
36    {"inform", OPT_INFORM, 'F', "Input format (DER or PEM)"},
37    {"outform", OPT_OUTFORM, 'F', "Output format (DER or PEM)"},
38    {"in", OPT_IN, '<', "Input file"},
39    {"out", OPT_OUT, '>', "Output file"},
40    {"topk8", OPT_TOPK8, '-', "Output PKCS8 file"},
41    {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"},
42    {"nocrypt", OPT_NOCRYPT, '-', "Use or expect unencrypted private key"},
43    OPT_R_OPTIONS,
44    {"v2", OPT_V2, 's', "Use PKCS#5 v2.0 and cipher"},
45    {"v1", OPT_V1, 's', "Use PKCS#5 v1.5 and cipher"},
46    {"v2prf", OPT_V2PRF, 's', "Set the PRF algorithm to use with PKCS#5 v2.0"},
47    {"iter", OPT_ITER, 'p', "Specify the iteration count"},
48    {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
49    {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
50    {"traditional", OPT_TRADITIONAL, '-', "use traditional format private key"},
51#ifndef OPENSSL_NO_ENGINE
52    {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
53#endif
54#ifndef OPENSSL_NO_SCRYPT
55    {"scrypt", OPT_SCRYPT, '-', "Use scrypt algorithm"},
56    {"scrypt_N", OPT_SCRYPT_N, 's', "Set scrypt N parameter"},
57    {"scrypt_r", OPT_SCRYPT_R, 's', "Set scrypt r parameter"},
58    {"scrypt_p", OPT_SCRYPT_P, 's', "Set scrypt p parameter"},
59#endif
60    {NULL}
61};
62
63int pkcs8_main(int argc, char **argv)
64{
65    BIO *in = NULL, *out = NULL;
66    ENGINE *e = NULL;
67    EVP_PKEY *pkey = NULL;
68    PKCS8_PRIV_KEY_INFO *p8inf = NULL;
69    X509_SIG *p8 = NULL;
70    const EVP_CIPHER *cipher = NULL;
71    char *infile = NULL, *outfile = NULL;
72    char *passinarg = NULL, *passoutarg = NULL, *prog;
73#ifndef OPENSSL_NO_UI_CONSOLE
74    char pass[APP_PASS_LEN];
75#endif
76    char *passin = NULL, *passout = NULL, *p8pass = NULL;
77    OPTION_CHOICE o;
78    int nocrypt = 0, ret = 1, iter = PKCS12_DEFAULT_ITER;
79    int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1;
80    int private = 0, traditional = 0;
81#ifndef OPENSSL_NO_SCRYPT
82    long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0;
83#endif
84
85    prog = opt_init(argc, argv, pkcs8_options);
86    while ((o = opt_next()) != OPT_EOF) {
87        switch (o) {
88        case OPT_EOF:
89        case OPT_ERR:
90 opthelp:
91            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
92            goto end;
93        case OPT_HELP:
94            opt_help(pkcs8_options);
95            ret = 0;
96            goto end;
97        case OPT_INFORM:
98            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
99                goto opthelp;
100            break;
101        case OPT_IN:
102            infile = opt_arg();
103            break;
104        case OPT_OUTFORM:
105            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
106                goto opthelp;
107            break;
108        case OPT_OUT:
109            outfile = opt_arg();
110            break;
111        case OPT_TOPK8:
112            topk8 = 1;
113            break;
114        case OPT_NOITER:
115            iter = 1;
116            break;
117        case OPT_NOCRYPT:
118            nocrypt = 1;
119            break;
120        case OPT_R_CASES:
121            if (!opt_rand(o))
122                goto end;
123            break;
124        case OPT_TRADITIONAL:
125            traditional = 1;
126            break;
127        case OPT_V2:
128            if (!opt_cipher(opt_arg(), &cipher))
129                goto opthelp;
130            break;
131        case OPT_V1:
132            pbe_nid = OBJ_txt2nid(opt_arg());
133            if (pbe_nid == NID_undef) {
134                BIO_printf(bio_err,
135                           "%s: Unknown PBE algorithm %s\n", prog, opt_arg());
136                goto opthelp;
137            }
138            break;
139        case OPT_V2PRF:
140            pbe_nid = OBJ_txt2nid(opt_arg());
141            if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0)) {
142                BIO_printf(bio_err,
143                           "%s: Unknown PRF algorithm %s\n", prog, opt_arg());
144                goto opthelp;
145            }
146            if (cipher == NULL)
147                cipher = EVP_aes_256_cbc();
148            break;
149        case OPT_ITER:
150            if (!opt_int(opt_arg(), &iter))
151                goto opthelp;
152            break;
153        case OPT_PASSIN:
154            passinarg = opt_arg();
155            break;
156        case OPT_PASSOUT:
157            passoutarg = opt_arg();
158            break;
159        case OPT_ENGINE:
160            e = setup_engine(opt_arg(), 0);
161            break;
162#ifndef OPENSSL_NO_SCRYPT
163        case OPT_SCRYPT:
164            scrypt_N = 16384;
165            scrypt_r = 8;
166            scrypt_p = 1;
167            if (cipher == NULL)
168                cipher = EVP_aes_256_cbc();
169            break;
170        case OPT_SCRYPT_N:
171            if (!opt_long(opt_arg(), &scrypt_N) || scrypt_N <= 0)
172                goto opthelp;
173            break;
174        case OPT_SCRYPT_R:
175            if (!opt_long(opt_arg(), &scrypt_r) || scrypt_r <= 0)
176                goto opthelp;
177            break;
178        case OPT_SCRYPT_P:
179            if (!opt_long(opt_arg(), &scrypt_p) || scrypt_p <= 0)
180                goto opthelp;
181            break;
182#endif
183        }
184    }
185    argc = opt_num_rest();
186    if (argc != 0)
187        goto opthelp;
188
189    private = 1;
190
191    if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
192        BIO_printf(bio_err, "Error getting passwords\n");
193        goto end;
194    }
195
196    if ((pbe_nid == -1) && cipher == NULL)
197        cipher = EVP_aes_256_cbc();
198
199    in = bio_open_default(infile, 'r', informat);
200    if (in == NULL)
201        goto end;
202    out = bio_open_owner(outfile, outformat, private);
203    if (out == NULL)
204        goto end;
205
206    if (topk8) {
207        pkey = load_key(infile, informat, 1, passin, e, "key");
208        if (pkey == NULL)
209            goto end;
210        if ((p8inf = EVP_PKEY2PKCS8(pkey)) == NULL) {
211            BIO_printf(bio_err, "Error converting key\n");
212            ERR_print_errors(bio_err);
213            goto end;
214        }
215        if (nocrypt) {
216            assert(private);
217            if (outformat == FORMAT_PEM) {
218                PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
219            } else if (outformat == FORMAT_ASN1) {
220                i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf);
221            } else {
222                BIO_printf(bio_err, "Bad format specified for key\n");
223                goto end;
224            }
225        } else {
226            X509_ALGOR *pbe;
227            if (cipher) {
228#ifndef OPENSSL_NO_SCRYPT
229                if (scrypt_N && scrypt_r && scrypt_p)
230                    pbe = PKCS5_pbe2_set_scrypt(cipher, NULL, 0, NULL,
231                                                scrypt_N, scrypt_r, scrypt_p);
232                else
233#endif
234                    pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, 0, NULL,
235                                            pbe_nid);
236            } else {
237                pbe = PKCS5_pbe_set(pbe_nid, iter, NULL, 0);
238            }
239            if (pbe == NULL) {
240                BIO_printf(bio_err, "Error setting PBE algorithm\n");
241                ERR_print_errors(bio_err);
242                goto end;
243            }
244            if (passout != NULL) {
245                p8pass = passout;
246            } else if (1) {
247                /* To avoid bit rot */
248#ifndef OPENSSL_NO_UI_CONSOLE
249                p8pass = pass;
250                if (EVP_read_pw_string
251                    (pass, sizeof(pass), "Enter Encryption Password:", 1)) {
252                    X509_ALGOR_free(pbe);
253                    goto end;
254                }
255            } else {
256#endif
257                BIO_printf(bio_err, "Password required\n");
258                goto end;
259            }
260            p8 = PKCS8_set0_pbe(p8pass, strlen(p8pass), p8inf, pbe);
261            if (p8 == NULL) {
262                X509_ALGOR_free(pbe);
263                BIO_printf(bio_err, "Error encrypting key\n");
264                ERR_print_errors(bio_err);
265                goto end;
266            }
267            assert(private);
268            if (outformat == FORMAT_PEM)
269                PEM_write_bio_PKCS8(out, p8);
270            else if (outformat == FORMAT_ASN1)
271                i2d_PKCS8_bio(out, p8);
272            else {
273                BIO_printf(bio_err, "Bad format specified for key\n");
274                goto end;
275            }
276        }
277
278        ret = 0;
279        goto end;
280    }
281
282    if (nocrypt) {
283        if (informat == FORMAT_PEM) {
284            p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL);
285        } else if (informat == FORMAT_ASN1) {
286            p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
287        } else {
288            BIO_printf(bio_err, "Bad format specified for key\n");
289            goto end;
290        }
291    } else {
292        if (informat == FORMAT_PEM) {
293            p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
294        } else if (informat == FORMAT_ASN1) {
295            p8 = d2i_PKCS8_bio(in, NULL);
296        } else {
297            BIO_printf(bio_err, "Bad format specified for key\n");
298            goto end;
299        }
300
301        if (p8 == NULL) {
302            BIO_printf(bio_err, "Error reading key\n");
303            ERR_print_errors(bio_err);
304            goto end;
305        }
306        if (passin != NULL) {
307            p8pass = passin;
308        } else if (1) {
309#ifndef OPENSSL_NO_UI_CONSOLE
310            p8pass = pass;
311            if (EVP_read_pw_string(pass, sizeof(pass), "Enter Password:", 0)) {
312                BIO_printf(bio_err, "Can't read Password\n");
313                goto end;
314            }
315        } else {
316#endif
317            BIO_printf(bio_err, "Password required\n");
318            goto end;
319        }
320        p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass));
321    }
322
323    if (p8inf == NULL) {
324        BIO_printf(bio_err, "Error decrypting key\n");
325        ERR_print_errors(bio_err);
326        goto end;
327    }
328
329    if ((pkey = EVP_PKCS82PKEY(p8inf)) == NULL) {
330        BIO_printf(bio_err, "Error converting key\n");
331        ERR_print_errors(bio_err);
332        goto end;
333    }
334
335    assert(private);
336    if (outformat == FORMAT_PEM) {
337        if (traditional)
338            PEM_write_bio_PrivateKey_traditional(out, pkey, NULL, NULL, 0,
339                                                 NULL, passout);
340        else
341            PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout);
342    } else if (outformat == FORMAT_ASN1) {
343        i2d_PrivateKey_bio(out, pkey);
344    } else {
345        BIO_printf(bio_err, "Bad format specified for key\n");
346        goto end;
347    }
348    ret = 0;
349
350 end:
351    X509_SIG_free(p8);
352    PKCS8_PRIV_KEY_INFO_free(p8inf);
353    EVP_PKEY_free(pkey);
354    release_engine(e);
355    BIO_free_all(out);
356    BIO_free(in);
357    OPENSSL_free(passin);
358    OPENSSL_free(passout);
359
360    return ret;
361}
Note: See TracBrowser for help on using the repository browser.