botan: Encode private keys as PKCS#8
authorTobias Brunner <tobias@strongswan.org>
Fri, 10 Aug 2018 07:02:26 +0000 (09:02 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 12 Sep 2018 14:25:00 +0000 (16:25 +0200)
Since we can now parse that encoding directly we can simplify the private
key export and stick to PKCS#8.

src/libstrongswan/plugins/botan/botan_ec_private_key.c
src/libstrongswan/plugins/botan/botan_rsa_private_key.c
src/libstrongswan/plugins/botan/botan_util.c
src/libstrongswan/plugins/botan/botan_util.h

index 78ba43f..f8dbb66 100644 (file)
@@ -209,123 +209,11 @@ METHOD(private_key_t, get_fingerprint, bool,
        return success;
 }
 
-/**
- * Get a field from the private key as chunk
- */
-static bool get_field_chunk(botan_privkey_t key, char *field, chunk_t *out)
-{
-       botan_mp_t val;
-
-       *out = chunk_empty;
-
-       if (botan_mp_init(&val))
-       {
-               return FALSE;
-       }
-
-       if (botan_privkey_get_field(val, key, field) ||
-               botan_mp_num_bytes(val, &out->len))
-       {
-               botan_mp_destroy(val);
-               return FALSE;
-       }
-
-       *out = chunk_alloc(out->len);
-
-       if (botan_mp_to_bin(val, out->ptr))
-       {
-               botan_mp_destroy(val);
-               chunk_free(out);
-               return FALSE;
-       }
-       botan_mp_destroy(val);
-       return TRUE;
-}
-
-/**
- * Encodes the public key as ASN.1 BIT STRING (0x04 || x || y)
- */
-static bool get_pubkey_bitstring(botan_privkey_t key, chunk_t *out)
-{
-       chunk_t p, x, y, pub;
-       size_t len;
-
-       if (!get_field_chunk(key, "p", &p))
-       {
-               return FALSE;
-       }
-       len = p.len;
-       chunk_free(&p);
-
-       if (!get_field_chunk(key, "public_x", &x))
-       {
-               return FALSE;
-       }
-       if (!get_field_chunk(key, "public_y", &y))
-       {
-               chunk_free(&x);
-               return FALSE;
-       }
-
-       pub = chunk_alloca(2 * len);
-       memset(pub.ptr, 0, pub.len);
-       memcpy(pub.ptr + (len - x.len), x.ptr, x.len);
-       memcpy(pub.ptr + len + (len - y.len), y.ptr, y.len);
-       chunk_free(&x);
-       chunk_free(&y);
-
-       *out = asn1_wrap(ASN1_BIT_STRING, "ccc",
-                                        /* unused bits in the bit string */
-                                        chunk_from_chars(0x00),
-                                        /* uncompressed format */
-                                        chunk_from_chars(0x04), pub);
-       return TRUE;
-}
-
 METHOD(private_key_t, get_encoding, bool,
        private_botan_ec_private_key_t *this, cred_encoding_type_t type,
        chunk_t *encoding)
 {
-       switch (type)
-       {
-               case PRIVKEY_ASN1_DER:
-               case PRIVKEY_PEM:
-               {
-                       chunk_t priv, pub;
-                       bool success = TRUE;
-
-                       if (!get_field_chunk(this->key, "x", &priv))
-                       {
-                               return FALSE;
-                       }
-                       if (!get_pubkey_bitstring(this->key, &pub))
-                       {
-                               chunk_clear(&priv);
-                               return FALSE;
-                       }
-
-                       *encoding = asn1_wrap(ASN1_SEQUENCE, "msmm",
-                                                                 asn1_integer("c", chunk_from_chars(0x01)),
-                                                                 asn1_wrap(ASN1_OCTET_STRING, "s", priv),
-                                                                 asn1_wrap(ASN1_CONTEXT_C_0, "m",
-                                                                               asn1_build_known_oid(this->oid)),
-                                                                 asn1_wrap(ASN1_CONTEXT_C_1, "m", pub));
-
-                       if (type == PRIVKEY_PEM)
-                       {
-                               chunk_t asn1_encoding = *encoding;
-
-                               success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
-                                                                                               NULL, encoding,
-                                                                                               CRED_PART_ECDSA_PRIV_ASN1_DER,
-                                                                                               asn1_encoding, CRED_PART_END);
-                               chunk_clear(&asn1_encoding);
-                       }
-                       return success;
-               }
-               default:
-                       return FALSE;
-       }
+       return botan_get_privkey_encoding(this->key, type, encoding);
 }
 
 METHOD(private_key_t, get_ref, private_key_t*,
index 8b2583b..558bb70 100644 (file)
@@ -257,38 +257,7 @@ METHOD(private_key_t, get_encoding, bool,
        private_botan_rsa_private_key_t *this, cred_encoding_type_t type,
        chunk_t *encoding)
 {
-       switch (type)
-       {
-               case PRIVKEY_ASN1_DER:
-               case PRIVKEY_PEM:
-               {
-                       uint32_t format = BOTAN_PRIVKEY_EXPORT_FLAG_DER;
-                       size_t len = 0;
-                       bool success = TRUE;
-
-                       if (type == PRIVKEY_PEM)
-                       {
-                               format = BOTAN_PRIVKEY_EXPORT_FLAG_PEM;
-                       }
-
-                       if (botan_privkey_rsa_get_privkey(this->key, NULL, &len, format)
-                               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
-                       {
-                               return FALSE;
-                       }
-
-                       *encoding = chunk_alloc(len);
-                       if (botan_privkey_rsa_get_privkey(this->key, encoding->ptr, &len,
-                                                                                         format))
-                       {
-                               chunk_clear(encoding);
-                               return FALSE;
-                       }
-                       return success;
-               }
-               default:
-                       return FALSE;
-       }
+       return botan_get_privkey_encoding(this->key, type, encoding);
 }
 
 METHOD(private_key_t, get_ref, private_key_t*,
index 9dcf592..860d376 100644 (file)
@@ -111,6 +111,39 @@ bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
 /*
  * Described in header
  */
+bool botan_get_privkey_encoding(botan_privkey_t key, cred_encoding_type_t type,
+                                                               chunk_t *encoding)
+{
+       uint32_t format = BOTAN_PRIVKEY_EXPORT_FLAG_DER;
+
+       switch (type)
+       {
+               case PRIVKEY_PEM:
+                       format = BOTAN_PRIVKEY_EXPORT_FLAG_PEM;
+                       /* fall-through */
+               case PRIVKEY_ASN1_DER:
+                       encoding->len = 0;
+                       if (botan_privkey_export(key, NULL, &encoding->len, format)
+                               != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
+                       {
+                               return FALSE;
+                       }
+                       *encoding = chunk_alloc(encoding->len);
+                       if (botan_privkey_export(key, encoding->ptr, &encoding->len,
+                                                                        format))
+                       {
+                               chunk_free(encoding);
+                               return FALSE;
+                       }
+                       return TRUE;
+               default:
+                       return FALSE;
+       }
+}
+
+/*
+ * Described in header
+ */
 bool botan_get_fingerprint(botan_pubkey_t pubkey, void *cache,
                                                   cred_encoding_type_t type, chunk_t *fp)
 {
index 1f4b96f..2c6b1f8 100644 (file)
@@ -65,6 +65,17 @@ bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
                                                chunk_t *encoding);
 
 /**
+ * Get the encoding of a botan_privkey_t.
+ *
+ * @param key          private key object
+ * @param type         encoding type
+ * @param encoding     allocated encoding
+ * @return                     TRUE if encoding successful
+ */
+bool botan_get_privkey_encoding(botan_privkey_t key, cred_encoding_type_t type,
+                                                               chunk_t *encoding);
+
+/**
  * Get the fingerprint of a botan_pubkey_t.
  *
  * @param pubkey       public key object