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

1.1       misho       1: /*
                      2:  * Copyright (C) 2009 Martin Willi
                      3:  * Copyright (C) 2015-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 <utils/debug.h>
                     23: #include <asn1/asn1.h>
                     24: #include <collections/linked_list.h>
                     25: #include <credentials/certificates/certificate.h>
                     26: #include <credentials/certificates/x509.h>
                     27: #include <credentials/certificates/ac.h>
                     28: 
                     29: /**
                     30:  * Issue an attribute certificate
                     31:  */
                     32: static int acert()
                     33: {
                     34:        cred_encoding_type_t form = CERT_ASN1_DER;
                     35:        hash_algorithm_t digest = HASH_UNKNOWN;
                     36:        signature_params_t *scheme = NULL;
                     37:        certificate_t *ac = NULL, *cert = NULL, *issuer =NULL;
                     38:        private_key_t *private = NULL;
                     39:        public_key_t *public = NULL;
                     40:        char *file = NULL, *hex = NULL, *issuercert = NULL, *issuerkey = NULL;
                     41:        char *error = NULL, *keyid = NULL;
                     42:        linked_list_t *groups;
                     43:        chunk_t serial = chunk_empty, encoding = chunk_empty;
                     44:        time_t not_before, not_after, lifetime = 24 * 60 * 60;
                     45:        char *datenb = NULL, *datena = NULL, *dateform = NULL;
                     46:        rng_t *rng;
                     47:        char *arg;
                     48:        bool pss = lib->settings->get_bool(lib->settings, "%s.rsa_pss", FALSE,
                     49:                                                                           lib->ns);
                     50: 
                     51:        groups = linked_list_create();
                     52: 
                     53:        while (TRUE)
                     54:        {
                     55:                switch (command_getopt(&arg))
                     56:                {
                     57:                        case 'h':
                     58:                                goto usage;
                     59:                        case 'g':
                     60:                                if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
                     61:                                {
                     62:                                        error = "invalid --digest type";
                     63:                                        goto usage;
                     64:                                }
                     65:                                continue;
                     66:                        case 'R':
                     67:                                if (streq(arg, "pss"))
                     68:                                {
                     69:                                        pss = TRUE;
                     70:                                }
                     71:                                else if (!streq(arg, "pkcs1"))
                     72:                                {
                     73:                                        error = "invalid RSA padding";
                     74:                                        goto usage;
                     75:                                }
                     76:                                continue;
                     77:                        case 'i':
                     78:                                file = arg;
                     79:                                continue;
                     80:                        case 'm':
                     81:                                groups->insert_last(groups, arg);
                     82:                                continue;
                     83:                        case 'c':
                     84:                                issuercert = arg;
                     85:                                continue;
                     86:                        case 'k':
                     87:                                issuerkey = arg;
                     88:                                continue;
                     89:                        case 'x':
                     90:                                keyid = arg;
                     91:                                continue;
                     92:                        case 'l':
                     93:                                lifetime = atoi(arg) * 60 * 60;
                     94:                                if (!lifetime)
                     95:                                {
                     96:                                        error = "invalid --lifetime value";
                     97:                                        goto usage;
                     98:                                }
                     99:                                continue;
                    100:                        case 'D':
                    101:                                dateform = arg;
                    102:                                continue;
                    103:                        case 'F':
                    104:                                datenb = arg;
                    105:                                continue;
                    106:                        case 'T':
                    107:                                datena = arg;
                    108:                                continue;
                    109:                        case 's':
                    110:                                hex = arg;
                    111:                                continue;
                    112:                        case 'f':
                    113:                                if (!get_form(arg, &form, CRED_CERTIFICATE))
                    114:                                {
                    115:                                        error = "invalid output format";
                    116:                                        goto usage;
                    117:                                }
                    118:                                continue;
                    119:                        case EOF:
                    120:                                break;
                    121:                        default:
                    122:                                error = "invalid --acert option";
                    123:                                goto usage;
                    124:                }
                    125:                break;
                    126:        }
                    127: 
                    128:        if (!calculate_lifetime(dateform, datenb, datena, lifetime,
                    129:                                                        &not_before, &not_after))
                    130:        {
                    131:                error = "invalid --not-before/after datetime";
                    132:                goto usage;
                    133:        }
                    134: 
                    135:        if (!issuercert)
                    136:        {
                    137:                error = "--issuercert is required";
                    138:                goto usage;
                    139:        }
                    140:        if (!issuerkey && !keyid)
                    141:        {
                    142:                error = "--issuerkey or --issuerkeyid is required";
                    143:                goto usage;
                    144:        }
                    145: 
                    146:        issuer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
                    147:                                                                BUILD_FROM_FILE, issuercert, BUILD_END);
                    148:        if (!issuer)
                    149:        {
                    150:                error = "parsing issuer certificate failed";
                    151:                goto end;
                    152:        }
                    153:        public = issuer->get_public_key(issuer);
                    154:        if (!public)
                    155:        {
                    156:                error = "extracting issuer certificate public key failed";
                    157:                goto end;
                    158:        }
                    159:        if (issuerkey)
                    160:        {
                    161:                private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
                    162:                                                                         public->get_type(public),
                    163:                                                                         BUILD_FROM_FILE, issuerkey, BUILD_END);
                    164:        }
                    165:        else
                    166:        {
                    167:                chunk_t chunk;
                    168: 
                    169:                chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
                    170:                private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
                    171:                                                                         BUILD_PKCS11_KEYID, chunk, BUILD_END);
                    172:                free(chunk.ptr);
                    173:        }
                    174:        if (!private)
                    175:        {
                    176:                error = "loading issuer private key failed";
                    177:                goto end;
                    178:        }
                    179:        if (!private->belongs_to(private, public))
                    180:        {
                    181:                error = "issuer private key does not match issuer certificate";
                    182:                goto end;
                    183:        }
                    184: 
                    185:        if (hex)
                    186:        {
                    187:                serial = chunk_from_hex(chunk_create(hex, strlen(hex)), NULL);
                    188:        }
                    189:        else
                    190:        {
                    191:                rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
                    192:                if (!rng)
                    193:                {
                    194:                        error = "no random number generator found";
                    195:                        goto end;
                    196:                }
                    197:                if (!rng_allocate_bytes_not_zero(rng, 8, &serial, FALSE))
                    198:                {
                    199:                        error = "failed to generate serial number";
                    200:                        rng->destroy(rng);
                    201:                        goto end;
                    202:                }
                    203:                serial.ptr[0] &= 0x7F;
                    204:                rng->destroy(rng);
                    205:        }
                    206: 
                    207:        if (file)
                    208:        {
                    209:                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
                    210:                                                                  BUILD_FROM_FILE, file, BUILD_END);
                    211:        }
                    212:        else
                    213:        {
                    214:                set_file_mode(stdin, CERT_ASN1_DER);
                    215:                if (!chunk_from_fd(0, &encoding))
                    216:                {
                    217:                        fprintf(stderr, "%s: ", strerror(errno));
                    218:                        error = "reading public key failed";
                    219:                        goto end;
                    220:                }
                    221:                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
                    222:                                                                  BUILD_BLOB, encoding, BUILD_END);
                    223:                chunk_free(&encoding);
                    224:        }
                    225:        if (!cert)
                    226:        {
                    227:                error = "parsing user certificate failed";
                    228:                goto end;
                    229:        }
                    230:        scheme = get_signature_scheme(private, digest, pss);
                    231:        if (!scheme)
                    232:        {
                    233:                error = "no signature scheme found";
                    234:                goto end;
                    235:        }
                    236: 
                    237:        ac = lib->creds->create(lib->creds,
                    238:                                                        CRED_CERTIFICATE, CERT_X509_AC,
                    239:                                                        BUILD_CERT, cert,
                    240:                                                        BUILD_NOT_BEFORE_TIME, not_before,
                    241:                                                        BUILD_NOT_AFTER_TIME, not_after,
                    242:                                                        BUILD_SERIAL, serial,
                    243:                                                        BUILD_AC_GROUP_STRINGS, groups,
                    244:                                                        BUILD_SIGNING_CERT, issuer,
                    245:                                                        BUILD_SIGNING_KEY, private,
                    246:                                                        BUILD_SIGNATURE_SCHEME, scheme,
                    247:                                                        BUILD_END);
                    248:        if (!ac)
                    249:        {
                    250:                error = "generating attribute certificate failed";
                    251:                goto end;
                    252:        }
                    253:        if (!ac->get_encoding(ac, form, &encoding))
                    254:        {
                    255:                error = "encoding attribute certificate failed";
                    256:                goto end;
                    257:        }
                    258:        set_file_mode(stdout, form);
                    259:        if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
                    260:        {
                    261:                error = "writing attribute certificate key failed";
                    262:                goto end;
                    263:        }
                    264: 
                    265: end:
                    266:        DESTROY_IF(ac);
                    267:        DESTROY_IF(cert);
                    268:        DESTROY_IF(issuer);
                    269:        DESTROY_IF(public);
                    270:        DESTROY_IF(private);
                    271:        groups->destroy(groups);
                    272:        signature_params_destroy(scheme);
                    273:        free(encoding.ptr);
                    274:        free(serial.ptr);
                    275: 
                    276:        if (error)
                    277:        {
                    278:                fprintf(stderr, "%s\n", error);
                    279:                return 1;
                    280:        }
                    281:        return 0;
                    282: 
                    283: usage:
                    284:        groups->destroy(groups);
                    285:        return command_usage(error);
                    286: }
                    287: 
                    288: /**
                    289:  * Register the command.
                    290:  */
                    291: static void __attribute__ ((constructor))reg()
                    292: {
                    293:        command_register((command_t) {
                    294:                acert, 'z', "acert",
                    295:                "issue an attribute certificate",
                    296:                {"[--in file] [--group name]* --issuerkey file|--issuerkeyid hex",
                    297:                 " --issuercert file [--serial hex] [--lifetime hours]",
                    298:                 " [--not-before datetime] [--not-after datetime] [--dateform form]",
                    299:                 "[--digest md5|sha1|sha224|sha256|sha384|sha512|sha3_224|sha3_256|sha3_384|sha3_512]",
                    300:                 "[--rsa-padding pkcs1|pss]",
                    301:                 "[--outform der|pem]"},
                    302:                {
                    303:                        {"help",                        'h', 0, "show usage information"},
                    304:                        {"in",                          'i', 1, "holder certificate, default: stdin"},
                    305:                        {"group",                       'm', 1, "group membership string to include"},
                    306:                        {"issuercert",          'c', 1, "issuer certificate file"},
                    307:                        {"issuerkey",           'k', 1, "issuer private key file"},
                    308:                        {"issuerkeyid",         'x', 1, "smartcard or TPM issuer private key object handle"},
                    309:                        {"serial",                      's', 1, "serial number in hex, default: random"},
                    310:                        {"lifetime",            'l', 1, "hours the acert is valid, default: 24"},
                    311:                        {"not-before",          'F', 1, "date/time the validity of the AC starts"},
                    312:                        {"not-after",           'T', 1, "date/time the validity of the AC ends"},
                    313:                        {"dateform",            'D', 1, "strptime(3) input format, default: %d.%m.%y %T"},
                    314:                        {"digest",                      'g', 1, "digest for signature creation, default: key-specific"},
                    315:                        {"rsa-padding",         'R', 1, "padding for RSA signatures, default: pkcs1"},
                    316:                        {"outform",                     'f', 1, "encoding of generated cert, default: der"},
                    317:                }
                    318:        });
                    319: }

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