allow choice of digest algorithm in certificate generation
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 28 Aug 2009 07:08:03 +0000 (09:08 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 28 Aug 2009 07:08:03 +0000 (09:08 +0200)
src/libstrongswan/credentials/builder.c
src/libstrongswan/credentials/builder.h
src/libstrongswan/credentials/credential_factory.c
src/libstrongswan/plugins/x509/x509_cert.c
src/pki/pki.c

index 601ae94..88df476 100644 (file)
@@ -36,6 +36,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
        "BUILD_NOT_BEFORE_TIME",
        "BUILD_NOT_AFTER_TIME",
        "BUILD_SERIAL",
+       "BUILD_DIGEST_ALG",
        "BUILD_IETF_GROUP_ATTR",
        "BUILD_CA_CERT",
        "BUILD_CERT",
index 678a844..650d052 100644 (file)
@@ -80,6 +80,8 @@ enum builder_part_t {
        BUILD_NOT_AFTER_TIME,
        /** a serial number in binary form, chunk_t */
        BUILD_SERIAL,
+       /** digest algorithm to be used for signature, int */
+       BUILD_DIGEST_ALG,
        /** a comma-separated list of ietf group attributes, char* */
        BUILD_IETF_GROUP_ATTR,
        /** a ca certificate, certificate_t* */
index 3cab10a..ac1f05b 100644 (file)
@@ -198,6 +198,9 @@ static void* create(private_credential_factory_t *this, credential_type_t type,
                                case BUILD_FROM_FD:
                                        builder->add(builder, part, va_arg(args, u_int));
                                        continue;
+                               case BUILD_DIGEST_ALG:
+                                       builder->add(builder, part, va_arg(args, int));
+                                       continue;
                                case BUILD_NOT_BEFORE_TIME:
                                case BUILD_NOT_AFTER_TIME:
                                        builder->add(builder, part, va_arg(args, time_t));
index c8d0dab..218723a 100644 (file)
@@ -1199,6 +1199,8 @@ struct private_builder_t {
        certificate_t *sign_cert;
        /** private key to sign, if we generate a new cert */
        private_key_t *sign_key;
+       /** digest algorithm to be used for signature */
+       hash_algorithm_t digest_alg;
 };
 
 /**
@@ -1236,7 +1238,7 @@ static bool generate(private_builder_t *this)
                this->cert->notBefore = time(NULL);
        }
        if (!this->cert->notAfter)
-       {       /* defaults to 1 years from now on */
+       {       /* defaults to 1 year from now */
                this->cert->notAfter = this->cert->notBefore + 60 * 60 * 24 * 365;
        }
        this->cert->flags = this->flags;
@@ -1245,16 +1247,54 @@ static bool generate(private_builder_t *this)
        switch (this->sign_key->get_type(this->sign_key))
        {
                case KEY_RSA:
-                       this->cert->algorithm = OID_SHA1_WITH_RSA;
-                       scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
+                       switch (this->digest_alg)
+                       {
+                               case HASH_MD5:
+                                       this->cert->algorithm = OID_MD5_WITH_RSA;
+                                       break;
+                               case HASH_SHA1:
+                                       this->cert->algorithm = OID_SHA1_WITH_RSA;
+                                       break;
+                               case HASH_SHA224:
+                                       this->cert->algorithm = OID_SHA224_WITH_RSA;
+                                       break;
+                               case HASH_SHA256:
+                                       this->cert->algorithm = OID_SHA256_WITH_RSA;
+                                       break;
+                               case HASH_SHA384:
+                                       this->cert->algorithm = OID_SHA384_WITH_RSA;
+                                       break;
+                               case HASH_SHA512:
+                                       this->cert->algorithm = OID_SHA512_WITH_RSA;
+                                       break;
+                               default:
+                                       return FALSE;
+                       }
                        break;
                case KEY_ECDSA:
-                       scheme = SIGN_ECDSA_WITH_SHA1_DER;
-                       this->cert->algorithm = OID_ECDSA_WITH_SHA1;
+                       switch (this->digest_alg)
+                       {
+                               case HASH_SHA1:
+                                       this->cert->algorithm = OID_ECDSA_WITH_SHA1;
+                                       break;
+                               case HASH_SHA256:
+                                       this->cert->algorithm = OID_ECDSA_WITH_SHA256;
+                                       break;
+                               case HASH_SHA384:
+                                       this->cert->algorithm = OID_ECDSA_WITH_SHA384;
+                                       break;
+                               case HASH_SHA512:
+                                       this->cert->algorithm = OID_ECDSA_WITH_SHA512;
+                                       break;
+                               default:
+                                       return FALSE;
+                       }
                        break;
                default:
                        return FALSE;
        }
+       scheme = signature_scheme_from_oid(this->cert->algorithm);
+
        if (!this->cert->public_key->get_encoding(this->cert->public_key,
                                                                                          KEY_PUB_SPKI_ASN1_DER, &key_info))
        {
@@ -1395,6 +1435,9 @@ static void add(private_builder_t *this, builder_part_t part, ...)
                        this->cert->serialNumber = chunk_clone(serial);
                        break;
                }
+               case BUILD_DIGEST_ALG:
+                       this->digest_alg = va_arg(args, int);
+                       break;
                default:
                        /* abort if unsupported option */
                        if (this->cert)
@@ -1425,6 +1468,7 @@ builder_t *x509_cert_builder(certificate_type_t type)
        this->flags = 0;
        this->sign_cert = NULL;
        this->sign_key = NULL;
+       this->digest_alg = HASH_SHA1;
        this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
        this->public.build = (void*(*)(builder_t *this))build;
        
index edb309f..13f2627 100644 (file)
@@ -438,6 +438,7 @@ static int keyid(int argc, char *argv[])
 static int self(int argc, char *argv[])
 {
        key_type_t type = KEY_RSA;
+       hash_algorithm_t digest = HASH_SHA1;
        certificate_t *cert;
        private_key_t *private;
        public_key_t *public;
@@ -453,6 +454,7 @@ static int self(int argc, char *argv[])
                { "dn", required_argument, NULL, 'd' },
                { "lifetime", required_argument, NULL, 'l' },
                { "serial", required_argument, NULL, 's' },
+               { "digest", required_argument, NULL, 'h' },
                { 0,0,0,0 }
        };
        
@@ -474,6 +476,36 @@ static int self(int argc, char *argv[])
                                        return usage("invalid input type");
                                }
                                continue;
+                       case 'h':
+                               if (streq(optarg, "md5"))
+                               {
+                                       digest = HASH_MD5;
+                               }
+                               else if (streq(optarg, "sha1"))
+                               {
+                                       digest = HASH_SHA1;
+                               }
+                               else if (streq(optarg, "sha224"))
+                               {
+                                       digest = HASH_SHA224;
+                               }
+                               else if (streq(optarg, "sha256"))
+                               {
+                                       digest = HASH_SHA256;
+                               }
+                               else if (streq(optarg, "sha384"))
+                               {
+                                       digest = HASH_SHA384;
+                               }
+                               else if (streq(optarg, "sha512"))
+                               {
+                                       digest = HASH_SHA512;
+                               }
+                               else
+                               {
+                                       return usage("invalid --digest type");
+                               }
+                               continue;
                        case 'i':
                                file = optarg;
                                continue;
@@ -557,7 +589,7 @@ static int self(int argc, char *argv[])
                                                BUILD_SIGNING_KEY, private, BUILD_PUBLIC_KEY, public,
                                                BUILD_SUBJECT, id, BUILD_NOT_BEFORE_TIME, not_before,
                                                BUILD_NOT_AFTER_TIME, not_after, BUILD_SERIAL, serial,
-                                               BUILD_END);
+                                               BUILD_DIGEST_ALG, digest, BUILD_END);
        private->destroy(private);
        public->destroy(public);
        id->destroy(id);