Annotation of embedaddon/strongswan/src/pki/commands/req.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2009 Martin Willi
                      3:  * Copyright (C) 2009-2017 Andreas Steffen
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include <time.h>
                     18: #include <errno.h>
                     19: 
                     20: #include "pki.h"
                     21: 
                     22: #include <collections/linked_list.h>
                     23: #include <credentials/certificates/certificate.h>
                     24: 
                     25: /**
                     26:  * Create a self-signed PKCS#10 certificate request.
                     27:  */
                     28: static int req()
                     29: {
                     30:        cred_encoding_type_t form = CERT_ASN1_DER;
                     31:        key_type_t type = KEY_ANY;
                     32:        hash_algorithm_t digest = HASH_UNKNOWN;
                     33:        signature_params_t *scheme = NULL;
                     34:        certificate_t *cert = NULL;
                     35:        private_key_t *private = NULL;
                     36:        char *file = NULL, *keyid = NULL, *dn = NULL, *error = NULL;
                     37:        identification_t *id = NULL;
                     38:        linked_list_t *san;
                     39:        chunk_t encoding = chunk_empty;
                     40:        chunk_t challenge_password = chunk_empty;
                     41:        char *arg;
                     42:        bool pss = lib->settings->get_bool(lib->settings, "%s.rsa_pss", FALSE,
                     43:                                                                           lib->ns);
                     44: 
                     45:        san = linked_list_create();
                     46: 
                     47:        while (TRUE)
                     48:        {
                     49:                switch (command_getopt(&arg))
                     50:                {
                     51:                        case 'h':
                     52:                                goto usage;
                     53:                        case 't':
                     54:                                if (streq(arg, "rsa"))
                     55:                                {
                     56:                                        type = KEY_RSA;
                     57:                                }
                     58:                                else if (streq(arg, "ecdsa"))
                     59:                                {
                     60:                                        type = KEY_ECDSA;
                     61:                                }
                     62:                                else if (streq(arg, "bliss"))
                     63:                                {
                     64:                                        type = KEY_BLISS;
                     65:                                }
                     66:                                else if (streq(arg, "priv"))
                     67:                                {
                     68:                                        type = KEY_ANY;
                     69:                                }
                     70:                                else
                     71:                                {
                     72:                                        error = "invalid input type";
                     73:                                        goto usage;
                     74:                                }
                     75:                                continue;
                     76:                        case 'g':
                     77:                                if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
                     78:                                {
                     79:                                        error = "invalid --digest type";
                     80:                                        goto usage;
                     81:                                }
                     82:                                continue;
                     83:                        case 'R':
                     84:                                if (streq(arg, "pss"))
                     85:                                {
                     86:                                        pss = TRUE;
                     87:                                }
                     88:                                else if (!streq(arg, "pkcs1"))
                     89:                                {
                     90:                                        error = "invalid RSA padding";
                     91:                                        goto usage;
                     92:                                }
                     93:                                continue;
                     94:                        case 'i':
                     95:                                file = arg;
                     96:                                continue;
                     97:                        case 'd':
                     98:                                dn = arg;
                     99:                                continue;
                    100:                        case 'a':
                    101:                                san->insert_last(san, identification_create_from_string(arg));
                    102:                                continue;
                    103:                        case 'p':
                    104:                                challenge_password = chunk_create(arg, strlen(arg));
                    105:                                continue;
                    106:                        case 'f':
                    107:                                if (!get_form(arg, &form, CRED_CERTIFICATE))
                    108:                                {
                    109:                                        error = "invalid output format";
                    110:                                        goto usage;
                    111:                                }
                    112:                                continue;
                    113:                        case 'x':
                    114:                                keyid = arg;
                    115:                                continue;
                    116:                        case EOF:
                    117:                                break;
                    118:                        default:
                    119:                                error = "invalid --req option";
                    120:                                goto usage;
                    121:                }
                    122:                break;
                    123:        }
                    124: 
                    125:        if (!dn)
                    126:        {
                    127:                error = "--dn is required";
                    128:                goto usage;
                    129:        }
                    130:        id = identification_create_from_string(dn);
                    131:        if (id->get_type(id) != ID_DER_ASN1_DN)
                    132:        {
                    133:                error = "supplied --dn is not a distinguished name";
                    134:                goto end;
                    135:        }
                    136:        if (file)
                    137:        {
                    138:                private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
                    139:                                                                         BUILD_FROM_FILE, file, BUILD_END);
                    140:        }
                    141:        else if (keyid)
                    142:        {
                    143:                chunk_t chunk;
                    144: 
                    145:                chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
                    146:                private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
                    147:                                                                          BUILD_PKCS11_KEYID, chunk, BUILD_END);
                    148:                free(chunk.ptr);
                    149:        }
                    150:        else
                    151:        {
                    152:                chunk_t chunk;
                    153: 
                    154:                set_file_mode(stdin, CERT_ASN1_DER);
                    155:                if (!chunk_from_fd(0, &chunk))
                    156:                {
                    157:                        fprintf(stderr, "reading private key failed: %s\n", strerror(errno));
                    158:                        error = "";
                    159:                        goto end;
                    160:                }
                    161:                private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
                    162:                                                                         BUILD_BLOB, chunk, BUILD_END);
                    163:                free(chunk.ptr);
                    164:        }
                    165:        if (!private)
                    166:        {
                    167:                error = "parsing private key failed";
                    168:                goto end;
                    169:        }
                    170:        scheme = get_signature_scheme(private, digest, pss);
                    171:        if (!scheme)
                    172:        {
                    173:                error = "no signature scheme found";
                    174:                goto end;
                    175:        }
                    176: 
                    177:        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PKCS10_REQUEST,
                    178:                                                          BUILD_SIGNING_KEY, private,
                    179:                                                          BUILD_SUBJECT, id,
                    180:                                                          BUILD_SUBJECT_ALTNAMES, san,
                    181:                                                          BUILD_CHALLENGE_PWD, challenge_password,
                    182:                                                          BUILD_SIGNATURE_SCHEME, scheme,
                    183:                                                          BUILD_END);
                    184:        if (!cert)
                    185:        {
                    186:                error = "generating certificate request failed";
                    187:                goto end;
                    188:        }
                    189:        if (!cert->get_encoding(cert, form, &encoding))
                    190:        {
                    191:                error = "encoding certificate request failed";
                    192:                goto end;
                    193:        }
                    194:        set_file_mode(stdout, form);
                    195:        if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
                    196:        {
                    197:                error = "writing certificate request failed";
                    198:                goto end;
                    199:        }
                    200: 
                    201: end:
                    202:        DESTROY_IF(id);
                    203:        DESTROY_IF(cert);
                    204:        DESTROY_IF(private);
                    205:        san->destroy_offset(san, offsetof(identification_t, destroy));
                    206:        signature_params_destroy(scheme);
                    207:        free(encoding.ptr);
                    208: 
                    209:        if (error)
                    210:        {
                    211:                fprintf(stderr, "%s\n", error);
                    212:                return 1;
                    213:        }
                    214:        return 0;
                    215: 
                    216: usage:
                    217:        san->destroy_offset(san, offsetof(identification_t, destroy));
                    218:        return command_usage(error);
                    219: }
                    220: 
                    221: /**
                    222:  * Register the command.
                    223:  */
                    224: static void __attribute__ ((constructor))reg()
                    225: {
                    226:        command_register((command_t) {
                    227:                req, 'r', "req",
                    228:                "create a PKCS#10 certificate request",
                    229:                {"[--in file|--keyid hex] [--type rsa|ecdsa|bliss|priv] --dn distinguished-name",
                    230:                 "[--san subjectAltName]+ [--password challengePassword]",
                    231:                 "[--digest md5|sha1|sha224|sha256|sha384|sha512|sha3_224|sha3_256|sha3_384|sha3_512]",
                    232:                 "[--rsa-padding pkcs1|pss]",
                    233:                 "[--outform der|pem]"},
                    234:                {
                    235:                        {"help",                'h', 0, "show usage information"},
                    236:                        {"in",                  'i', 1, "private key input file, default: stdin"},
                    237:                        {"keyid",               'x', 1, "smartcard or TPM private key object handle"},
                    238:                        {"type",                't', 1, "type of input key, default: priv"},
                    239:                        {"dn",                  'd', 1, "subject distinguished name"},
                    240:                        {"san",                 'a', 1, "subjectAltName to include in cert request"},
                    241:                        {"password",    'p', 1, "challengePassword to include in cert request"},
                    242:                        {"digest",              'g', 1, "digest for signature creation, default: key-specific"},
                    243:                        {"rsa-padding", 'R', 1, "padding for RSA signatures, default: pkcs1"},
                    244:                        {"outform",             'f', 1, "encoding of generated request, default: der"},
                    245:                }
                    246:        });
                    247: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>