Annotation of embedaddon/strongswan/src/pki/commands/acert.c, revision 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>