Store and parse BLISS private and public keys in DER and PEM format
authorAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 4 Nov 2014 19:51:33 +0000 (20:51 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 29 Nov 2014 13:51:16 +0000 (14:51 +0100)
Additionally generate SHA-1 fingerprints of raw BLISS subjectPublicKey
and subjectPublicKeyInfo objects.

Some basic functions used by the bliss_public_key class are shared
with the bliss_private_key class.

src/libstrongswan/asn1/oid.txt
src/libstrongswan/credentials/cred_encoding.h
src/libstrongswan/plugins/bliss/bliss_private_key.c
src/libstrongswan/plugins/bliss/bliss_public_key.c
src/libstrongswan/plugins/pem/pem_encoder.c
src/libstrongswan/plugins/pem/pem_plugin.c
src/libstrongswan/plugins/pkcs1/pkcs1_builder.c
src/pki/commands/print.c
src/pki/commands/pub.c

index 5d74f40..e0e0e18 100644 (file)
                 0x03         "e-voting"
                 0x05         "BLISS"
                   0x01       "keyType"
-                    0x01     "blissPublicKey"                  OID_BLISS
+                    0x01     "blissPublicKey"                  OID_BLISS_PUBLICKEY
                   0x02       "parameters"
                     0x01     "BLISS-I"                                 OID_BLISS_I
                     0x02     "BLISS-II"                                        OID_BLISS_II
index a6c9c30..b4d1f4c 100644 (file)
@@ -144,6 +144,10 @@ enum cred_encoding_part_t {
        CRED_PART_PKCS10_ASN1_DER,
        /** a PGP encoded certificate */
        CRED_PART_PGP_CERT,
+       /** a DER encoded BLISS public key */
+       CRED_PART_BLISS_PUB_ASN1_DER,
+       /** a DER encoded BLISS private key */
+       CRED_PART_BLISS_PRIV_ASN1_DER,
 
        CRED_PART_END,
 };
index 2af6f2b..df7bbbf 100644 (file)
@@ -18,6 +18,9 @@
 #include "bliss_fft.h"
 
 #include <crypto/mgf1/mgf1_bitspender.h>
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <asn1/oid.h>
 
 #define _GNU_SOURCE
 #include <stdlib.h>
@@ -27,6 +30,18 @@ typedef struct private_bliss_private_key_t private_bliss_private_key_t;
 #define SECRET_KEY_TRIALS_MAX  30
 
 /**
+ * Functions shared with bliss_public_key class
+ */
+extern uint32_t* bliss_public_key_from_asn1(chunk_t object, int n);
+
+extern chunk_t bliss_public_key_encode(uint32_t *pubkey, int n);
+
+extern chunk_t bliss_public_key_info_encode(int oid, uint32_t *pubkey, int n);
+
+extern bool bliss_public_key_fingerprint(int oid, uint32_t *pubkey, int n,
+                                                                                cred_encoding_type_t type, chunk_t *fp);
+
+/**
  * Private data of a bliss_private_key_t object.
  */
 struct private_bliss_private_key_t {
@@ -41,6 +56,21 @@ struct private_bliss_private_key_t {
        bliss_param_set_t *set;
 
        /**
+        * BLISS secret key S1 (coefficients of polynomial f)
+        */
+       int8_t *s1;
+
+       /**
+        * BLISS secret key S2 (coefficients of polynomial 2g + 1)
+        */
+       int8_t *s2;
+
+       /**
+        * BLISS public key a (coefficients of polynomial (2g + 1)/f)
+        */
+       uint32_t *a;
+
+       /**
         * reference count
         */
        refcount_t ref;
@@ -87,7 +117,14 @@ METHOD(private_key_t, get_keysize, int,
 METHOD(private_key_t, get_public_key, public_key_t*,
        private_bliss_private_key_t *this)
 {
-       public_key_t *public = NULL;
+       public_key_t *public;
+       chunk_t pubkey;
+
+       pubkey = bliss_public_key_info_encode(this->set->oid, this->a,
+                                                                                 this->set->n);
+       public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_BLISS,
+                                                               BUILD_BLOB_ASN1_DER, pubkey, BUILD_END);
+       free(pubkey.ptr);
 
        return public;
 }
@@ -96,17 +133,55 @@ METHOD(private_key_t, get_encoding, bool,
        private_bliss_private_key_t *this, cred_encoding_type_t type,
        chunk_t *encoding)
 {
-       bool success = TRUE;
+       switch (type)
+       {
+               case PRIVKEY_ASN1_DER:
+               case PRIVKEY_PEM:
+               {
+                       chunk_t s1_chunk, s2_chunk, pubkey;
+                       bool success = TRUE;
 
-       *encoding = chunk_empty;
+                       pubkey = bliss_public_key_encode(this->a, this->set->n);
 
-       return success;
+                       /* Build private key as two polynomials with 8 bit coefficients */
+                       s1_chunk = chunk_create(this->s1, this->set->n);
+                       s2_chunk = chunk_create(this->s2, this->set->n);
+
+                       *encoding = asn1_wrap(ASN1_SEQUENCE, "mmss",
+                                                       asn1_build_known_oid(this->set->oid),
+                                                       pubkey,
+                                                       asn1_simple_object(ASN1_OCTET_STRING, s1_chunk),
+                                                       asn1_simple_object(ASN1_OCTET_STRING, s2_chunk)
+                                               );
+
+                       if (type == PRIVKEY_PEM)
+                       {
+                               chunk_t asn1_encoding = *encoding;
+
+                               success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
+                                                               NULL, encoding, CRED_PART_BLISS_PRIV_ASN1_DER,
+                                                               asn1_encoding, CRED_PART_END);
+                               chunk_clear(&asn1_encoding);
+                       }
+                       return success;
+               }
+               default:
+                       return FALSE;
+       }
 }
 
 METHOD(private_key_t, get_fingerprint, bool,
        private_bliss_private_key_t *this, cred_encoding_type_t type, chunk_t *fp)
 {
-       bool success = FALSE;
+       bool success;
+
+       if (lib->encoding->get_cache(lib->encoding, type, this, fp))
+       {
+               return TRUE;
+       }
+       success = bliss_public_key_fingerprint(this->set->oid, this->a,
+                                                                                  this->set->n, type, fp);
+       lib->encoding->cache(lib->encoding, type, this, *fp);
 
        return success;
 }
@@ -123,6 +198,10 @@ METHOD(private_key_t, destroy, void,
 {
        if (ref_put(&this->ref))
        {
+               lib->encoding->clear_cache(lib->encoding, this);
+               free(this->s1);
+               free(this->s2);
+               free(this->a);
                free(this);
        }
 }
@@ -438,9 +517,8 @@ bliss_private_key_t *bliss_private_key_gen(key_type_t type, va_list args)
        private_bliss_private_key_t *this;
        u_int key_size = 1;
        int i, n, trials = 0;
-       int8_t *s1 = NULL, *s2 = NULL;
+       uint32_t *A, *S1, *S2;
        uint16_t q;
-       uint32_t *a, *A, *S1, *S2;
        bool success = FALSE;
        bliss_param_set_t *set;
        bliss_fft_t *fft;
@@ -487,8 +565,8 @@ bliss_private_key_t *bliss_private_key_gen(key_type_t type, va_list args)
        /* Some vectors needed to derive the publi key */
        S1 = malloc(n * sizeof(uint32_t));
        S2 = malloc(n * sizeof(uint32_t));
-       A =  malloc(n * sizeof(uint32_t));
-       a =  malloc(n * sizeof(uint32_t));
+       A = malloc(n * sizeof(uint32_t));
+       this->a = malloc(n * sizeof(uint32_t));
 
        /* Instantiate a true random generator */
        rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
@@ -496,7 +574,7 @@ bliss_private_key_t *bliss_private_key_gen(key_type_t type, va_list args)
        /* Loop until we have an invertible polynomial s1 */
        do
        {
-               if (!create_secret(this, rng, &s1, &s2, &trials))
+               if (!create_secret(this, rng, &this->s1, &this->s2, &trials))
                {
                        break;
                }
@@ -504,8 +582,8 @@ bliss_private_key_t *bliss_private_key_gen(key_type_t type, va_list args)
                /* Convert signed arrays to unsigned arrays before FFT */
                for (i = 0; i < n; i++)
                {
-                       S1[i] = (s1[i] < 0) ? s1[i] + q : s1[i];
-                       S1[i] = (s2[i] < 0) ? s2[i] + q : s2[i];
+                       S1[i] = (this->s1[i] < 0) ? this->s1[i] + q :  this->s1[i];
+                       S2[i] = (this->s2[i] > 0) ? q - this->s2[i] : -this->s2[i];
                }
                fft->transform(fft, S1, S1, FALSE);
                fft->transform(fft, S2, S2, FALSE);
@@ -516,10 +594,10 @@ bliss_private_key_t *bliss_private_key_gen(key_type_t type, va_list args)
                        if (S1[i] == 0)
                        {
                                DBG1(DBG_LIB, "S1[%d] is zero - s1 is not invertible", i);
-                               free(s1);
-                               s1 = NULL;
-                               free(s2);
-                               s2 = NULL;
+                               free(this->s1);
+                               free(this->s2);
+                               this->s1 = NULL;
+                               this->s2 = NULL;
                                success = FALSE;
                                break;
                        }
@@ -534,13 +612,13 @@ bliss_private_key_t *bliss_private_key_gen(key_type_t type, va_list args)
 
        if (success)
        {
-               fft->transform(fft, A, a, TRUE);
+               fft->transform(fft, A, this->a, TRUE);
 
                DBG4(DBG_LIB, "   i   f   g     a     F     G     A");
                for (i = 0; i < n; i++)
                {
                        DBG4(DBG_LIB, "%4d %3d %3d %5u %5u %5u %5u",
-                                i, s1[i], s2[i], a[i], S1[i], S2[i], A[i]);
+                                i, this->s1[i], this->s2[i], this->a[i], S1[i], S2[i], A[i]);
                }
        }
        else
@@ -551,9 +629,6 @@ bliss_private_key_t *bliss_private_key_gen(key_type_t type, va_list args)
        /* Cleanup */
        fft->destroy(fft);
        rng->destroy(rng);
-       free(s1);
-       free(s2);
-       free(a);
        free(A);
        free(S1);
        free(S2);
@@ -562,24 +637,107 @@ bliss_private_key_t *bliss_private_key_gen(key_type_t type, va_list args)
 }
 
 /**
+ * ASN.1 definition of a BLISS private key
+ */
+static const asn1Object_t privkeyObjects[] = {
+       { 0, "BLISSPrivateKey",         ASN1_SEQUENCE,     ASN1_NONE }, /*  0 */
+       { 1,   "keyType",                       ASN1_OID,          ASN1_BODY }, /*  1 */
+       { 1,   "public",                        ASN1_OCTET_STRING, ASN1_BODY }, /*  2 */
+       { 1,   "secret1",                       ASN1_OCTET_STRING, ASN1_BODY }, /*  3 */
+       { 1,   "secret2",                       ASN1_OCTET_STRING, ASN1_BODY }, /*  4 */
+       { 0, "exit",                            ASN1_EOC,          ASN1_EXIT }
+};
+#define PRIV_KEY_TYPE                  1
+#define PRIV_KEY_PUBLIC                        2
+#define PRIV_KEY_SECRET1               3
+#define PRIV_KEY_SECRET2               4
+
+/**
  * See header.
  */
 bliss_private_key_t *bliss_private_key_load(key_type_t type, va_list args)
 {
        private_bliss_private_key_t *this;
+       chunk_t key = chunk_empty, object;
+       asn1_parser_t *parser;
+       bool success = FALSE;
+       int objectID, oid;
 
        while (TRUE)
        {
                switch (va_arg(args, builder_part_t))
                {
+                       case BUILD_BLOB_ASN1_DER:
+                               key = va_arg(args, chunk_t);
+                               continue;
+                       case BUILD_END:
+                               break;
                        default:
                                return NULL;
                }
                break;
        }
 
+       if (key.len == 0)
+       {
+               return NULL;
+       }
        this = bliss_private_key_create_empty();
 
+       parser = asn1_parser_create(privkeyObjects, key);
+       parser->set_flags(parser, FALSE, TRUE);
+
+       while (parser->iterate(parser, &objectID, &object))
+       {
+               switch (objectID)
+               {
+                       case PRIV_KEY_TYPE:
+                               oid = asn1_known_oid(object);
+                               if (oid == OID_UNKNOWN)
+                               {
+                                       goto end;
+                               }
+                               this->set = bliss_param_set_get_by_oid(oid);
+                               if (this->set == NULL)
+                               {
+                                       goto end;
+                               }
+                               break;
+                       case PRIV_KEY_PUBLIC:
+                               if (object.len != 2*this->set->n)
+                               {
+                                       goto end;
+                               }
+                               this->a = bliss_public_key_from_asn1(object, this->set->n);
+                               break;
+                       case PRIV_KEY_SECRET1:
+                               if (object.len != this->set->n)
+                               {
+                                       goto end;
+                               }
+                               this->s1 = malloc(this->set->n);
+                               memcpy(this->s1, object.ptr, object.len);
+                               break;
+                       case PRIV_KEY_SECRET2:
+                               if (object.len != this->set->n)
+                               {
+                                       goto end;
+                               }
+                               this->s2 = malloc(this->set->n);
+                               memcpy(this->s2, object.ptr, object.len);
+                               break;
+               }
+       }
+       success = parser->success(parser);
+
+end:
+       parser->destroy(parser);
+       if (!success)
+       {
+               destroy(this);
+               return NULL;
+       }
+
        return &this->public;
 }
 
index 002bf34..9d39ae6 100644 (file)
  */
 
 #include "bliss_public_key.h"
+#include "bliss_param_set.h"
+
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <asn1/oid.h>
 
 typedef struct private_bliss_public_key_t private_bliss_public_key_t;
 
@@ -27,9 +32,14 @@ struct private_bliss_public_key_t {
        bliss_public_key_t public;
 
        /**
-        * BLISS type
+        * BLISS signature parameter set
         */
-       u_int key_size;
+       bliss_param_set_t *set;
+
+       /**
+        * BLISS public key a (coefficients of polynomial (2g + 1)/f)
+        */
+       uint32_t *a;
 
        /**
         * reference counter
@@ -72,7 +82,104 @@ METHOD(public_key_t, encrypt_, bool,
 METHOD(public_key_t, get_keysize, int,
        private_bliss_public_key_t *this)
 {
-       return this->key_size;
+       return this->set->strength;
+}
+
+/**
+ * Parse an ASN.1 OCTET STRING into an array of public key coefficients
+ */
+uint32_t* bliss_public_key_from_asn1(chunk_t object, int n)
+{
+       uint32_t *pubkey;
+       uint16_t coeff;
+       u_char *pos;
+       int i;
+
+       pubkey = malloc(n * sizeof(uint32_t));
+       pos = object.ptr;
+
+       for (i = 0; i < n; i++)
+       {
+               coeff = untoh16(pos);
+               pubkey[i] = (uint32_t)coeff;
+               pos += 2;
+       }
+
+       return pubkey;
+}
+
+/**
+ * Encode a raw BLISS subjectPublicKey in ASN.1 DER format
+ */
+chunk_t bliss_public_key_encode(uint32_t *pubkey, int n)
+{
+       u_char *pos;
+       chunk_t encoding;
+       int i;
+
+       pos = asn1_build_object(&encoding, ASN1_OCTET_STRING, 2 * n);
+
+       for (i = 0; i < n; i++)
+       {
+               htoun16(pos, (uint16_t)pubkey[i]);
+               pos += 2;
+       }
+
+       return encoding;
+}
+
+/**
+ * Encode a BLISS subjectPublicKeyInfo record in ASN.1 DER format
+ */
+chunk_t bliss_public_key_info_encode(int oid, uint32_t *pubkey, int n)
+{
+       chunk_t encoding, pubkey_encoding;
+
+       pubkey_encoding = bliss_public_key_encode(pubkey, n);
+
+       encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
+                                       asn1_wrap(ASN1_SEQUENCE, "mm",
+                                               asn1_build_known_oid(OID_BLISS_PUBLICKEY),
+                                               asn1_build_known_oid(oid)),
+                                       asn1_bitstring("m", pubkey_encoding));
+
+       return encoding;
+}
+
+/**
+ * Generate a BLISS public key fingerprint
+ */
+bool bliss_public_key_fingerprint(int oid, uint32_t *pubkey, int n,
+                                                                 cred_encoding_type_t type, chunk_t *fp)
+{
+       hasher_t *hasher;
+       chunk_t key;
+
+       switch (type)
+       {
+               case KEYID_PUBKEY_SHA1:
+                       key = bliss_public_key_encode(pubkey, n);
+                       break;
+               case KEYID_PUBKEY_INFO_SHA1:
+                       key = bliss_public_key_info_encode(oid, pubkey, n);
+                       break;
+               default:
+                       return FALSE;
+       }
+
+       hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+       if (!hasher || !hasher->allocate_hash(hasher, key, fp))
+       {
+               DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
+               DESTROY_IF(hasher);
+               free(key.ptr);
+
+               return FALSE;
+       }
+       hasher->destroy(hasher);
+       free(key.ptr);
+
+       return TRUE;
 }
 
 METHOD(public_key_t, get_encoding, bool,
@@ -81,15 +188,33 @@ METHOD(public_key_t, get_encoding, bool,
 {
        bool success = TRUE;
 
-       *encoding = chunk_empty;
+       *encoding = bliss_public_key_info_encode(this->set->oid, this->a,
+                                                                                        this->set->n);
+
+       if (type != PUBKEY_SPKI_ASN1_DER)
+       {
+               chunk_t asn1_encoding = *encoding;
 
+               success = lib->encoding->encode(lib->encoding, type,
+                                               NULL, encoding, CRED_PART_BLISS_PUB_ASN1_DER,
+                                               asn1_encoding, CRED_PART_END);
+               chunk_clear(&asn1_encoding);
+       }
        return success;
 }
 
 METHOD(public_key_t, get_fingerprint, bool,
        private_bliss_public_key_t *this, cred_encoding_type_t type, chunk_t *fp)
 {
-       bool success = FALSE;
+       bool success;
+
+       if (lib->encoding->get_cache(lib->encoding, type, this, fp))
+       {
+               return TRUE;
+       }
+       success = bliss_public_key_fingerprint(this->set->oid, this->a,
+                                                                                  this->set->n, type, fp);
+       lib->encoding->cache(lib->encoding, type, this, *fp);
 
        return success;
 }
@@ -106,21 +231,42 @@ METHOD(public_key_t, destroy, void,
 {
        if (ref_put(&this->ref))
        {
+               lib->encoding->clear_cache(lib->encoding, this);
+               free(this->a);
                free(this);
        }
 }
 
 /**
+ * ASN.1 definition of a BLISS public key
+ */
+static const asn1Object_t pubkeyObjects[] = {
+       { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE,              ASN1_OBJ  }, /*  0 */
+       { 1,   "algorithm",                     ASN1_EOC,                       ASN1_RAW  }, /*  1 */
+       { 1,   "subjectPublicKey",      ASN1_BIT_STRING,        ASN1_BODY }, /*  2 */
+       { 0, "exit",                            ASN1_EOC,                       ASN1_EXIT }
+};
+#define BLISS_SUBJECT_PUBLIC_KEY_ALGORITHM     1
+#define BLISS_SUBJECT_PUBLIC_KEY                       2
+
+/**
  * See header.
  */
 bliss_public_key_t *bliss_public_key_load(key_type_t type, va_list args)
 {
        private_bliss_public_key_t *this;
+       chunk_t blob = chunk_empty, object, param;
+       asn1_parser_t *parser;
+       bool success = FALSE;
+       int objectID, oid;
 
        while (TRUE)
        {
                switch (va_arg(args, builder_part_t))
                {
+                       case BUILD_BLOB_ASN1_DER:
+                               blob = va_arg(args, chunk_t);
+                               continue;
                        case BUILD_END:
                                break;
                        default:
@@ -129,6 +275,11 @@ bliss_public_key_t *bliss_public_key_load(key_type_t type, va_list args)
                break;
        }
 
+       if (blob.len == 0)
+       {
+               return NULL;
+       }
+
        INIT(this,
                .public = {
                        .key = {
@@ -147,5 +298,65 @@ bliss_public_key_t *bliss_public_key_load(key_type_t type, va_list args)
                .ref = 1,
        );
 
+       parser = asn1_parser_create(pubkeyObjects, blob);
+
+       while (parser->iterate(parser, &objectID, &object))
+       {
+               switch (objectID)
+               {
+                       case BLISS_SUBJECT_PUBLIC_KEY_ALGORITHM:
+                       {
+                               oid = asn1_parse_algorithmIdentifier(object,
+                                                               parser->get_level(parser)+1, &param);
+                               if (oid != OID_BLISS_PUBLICKEY)
+                               {
+                                       goto end;
+                               }
+                               if (!asn1_parse_simple_object(&param, ASN1_OID,
+                                                               parser->get_level(parser)+3, "blissKeyType"))
+                               {
+                                       goto end;
+                               }
+                               oid = asn1_known_oid(param);
+                               if (oid == OID_UNKNOWN)
+                               {
+                                       goto end;
+                               }
+                               this->set = bliss_param_set_get_by_oid(oid);
+                               if (this->set == NULL)
+                               {
+                                       goto end;
+                               }
+                               break;
+                       }
+                       case BLISS_SUBJECT_PUBLIC_KEY:
+                               if (object.len > 0 && *object.ptr == 0x00)
+                               {
+                                       /* skip initial bit string octet defining 0 unused bits */
+                                       object = chunk_skip(object, 1);
+                               }
+                               if (!asn1_parse_simple_object(&object, ASN1_OCTET_STRING,
+                                               parser->get_level(parser)+1, "blissPublicKey"))
+                               {
+                                       goto end;
+                               }
+                               if (object.len != 2*this->set->n)
+                               {
+                                       goto end;
+                               }
+                               this->a = bliss_public_key_from_asn1(object, this->set->n);
+                               break;
+               }
+       }
+       success = parser->success(parser);
+
+end:
+       parser->destroy(parser);
+       if (!success)
+       {
+               destroy(this);
+               return NULL;
+       }
+
        return &this->public;
 }
index df4b77c..35ea3e8 100644 (file)
@@ -53,6 +53,11 @@ bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
                                        break;
                                }
                        }
+                       if (cred_encoding_args(args, CRED_PART_BLISS_PUB_ASN1_DER,
+                                                                  &asn1, CRED_PART_END))
+                       {
+                               break;
+                       }
                        return FALSE;
                case PRIVKEY_PEM:
                        label ="RSA PRIVATE KEY";
@@ -86,6 +91,12 @@ bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
                                label ="EC PRIVATE KEY";
                                break;
                        }
+                       if (cred_encoding_args(args, CRED_PART_BLISS_PRIV_ASN1_DER,
+                                                                  &asn1, CRED_PART_END))
+                       {
+                               label ="BLISS PRIVATE KEY";
+                               break;
+                       }
                        return FALSE;
                case CERT_PEM:
                        if (cred_encoding_args(args, CRED_PART_X509_ASN1_DER,
index e7edd7b..d5bcbb6 100644 (file)
@@ -60,6 +60,9 @@ METHOD(plugin_t, get_features, int,
                        PLUGIN_PROVIDE(PRIVKEY, KEY_DSA),
                                PLUGIN_DEPENDS(PRIVKEY, KEY_DSA),
                                PLUGIN_SDEPEND(HASHER, HASH_MD5),
+               PLUGIN_REGISTER(PRIVKEY, pem_private_key_load, FALSE),
+                       PLUGIN_PROVIDE(PRIVKEY, KEY_BLISS),
+                               PLUGIN_DEPENDS(PRIVKEY, KEY_BLISS),
 
                /* public key PEM decoding */
                PLUGIN_REGISTER(PUBKEY, pem_public_key_load, FALSE),
@@ -74,6 +77,8 @@ METHOD(plugin_t, get_features, int,
                PLUGIN_REGISTER(PUBKEY, pem_public_key_load, FALSE),
                        PLUGIN_PROVIDE(PUBKEY, KEY_DSA),
                                PLUGIN_DEPENDS(PUBKEY, KEY_DSA),
+               PLUGIN_REGISTER(PUBKEY, pem_public_key_load, FALSE),
+                       PLUGIN_PROVIDE(PUBKEY, KEY_BLISS),
 
                /* certificate PEM decoding */
                PLUGIN_REGISTER(CERT_DECODE, pem_certificate_load, FALSE),
index c6661fc..767b3ac 100644 (file)
@@ -63,11 +63,18 @@ static public_key_t *parse_public_key(chunk_t blob)
                                }
                                else if (oid == OID_EC_PUBLICKEY)
                                {
-                                       /* we need the whole subjectPublicKeyInfo for EC public keys */
+                                       /* Need the whole subjectPublicKeyInfo for EC public keys */
                                        key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
                                                                KEY_ECDSA, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
                                        goto end;
                                }
+                               else if (oid == OID_BLISS_PUBLICKEY)
+                               {
+                                       /* Need the whole subjectPublicKeyInfo for BLISS public keys */
+                                       key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
+                                                               KEY_BLISS, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
+                                       goto end;
+                               }
                                else
                                {
                                        /* key type not supported */
index a8a4e83..fa69de1 100644 (file)
 static void print_pubkey(public_key_t *key)
 {
        chunk_t chunk;
+       key_type_t type;
+
+       type = key->get_type(key);
+       printf("pubkey:    %N %d bits%s\n", key_type_names, type,
+                       key->get_keysize(key), (type == KEY_BLISS) ? " strength" : "");
 
-       printf("pubkey:    %N %d bits\n", key_type_names, key->get_type(key),
-                  key->get_keysize(key));
        if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &chunk))
        {
                printf("keyid:     %#B\n", &chunk);
@@ -596,6 +599,11 @@ static int print()
                                        type = CRED_PRIVATE_KEY;
                                        subtype = KEY_ECDSA;
                                }
+                               else if (streq(arg, "bliss-priv"))
+                               {
+                                       type = CRED_PRIVATE_KEY;
+                                       subtype = KEY_BLISS;
+                               }
                                else
                                {
                                        return command_usage( "invalid input type");
@@ -668,7 +676,7 @@ static void __attribute__ ((constructor))reg()
        command_register((command_t)
                { print, 'a', "print",
                "print a credential in a human readable form",
-               {"[--in file] [--type rsa-priv|ecdsa-priv|pub|x509|crl|ac]"},
+               {"[--in file] [--type rsa-priv|ecdsa-priv|bliss-priv|pub|x509|crl|ac]"},
                {
                        {"help",        'h', 0, "show usage information"},
                        {"in",          'i', 1, "input file, default: stdin"},
index b8d2f70..843b784 100644 (file)
@@ -53,6 +53,11 @@ static int pub()
                                        type = CRED_PRIVATE_KEY;
                                        subtype = KEY_ECDSA;
                                }
+                               else if (streq(arg, "bliss"))
+                               {
+                                       type = CRED_PRIVATE_KEY;
+                                       subtype = KEY_BLISS;
+                               }
                                else if (streq(arg, "pub"))
                                {
                                        type = CRED_PUBLIC_KEY;
@@ -183,7 +188,7 @@ static void __attribute__ ((constructor))reg()
        command_register((command_t) {
                pub, 'p', "pub",
                "extract the public key from a private key/certificate",
-               {"[--in file|--keyid hex] [--type rsa|ecdsa|pub|pkcs10|x509]",
+               {"[--in file|--keyid hex] [--type rsa|ecdsa|bliss|pub|pkcs10|x509]",
                 "[--outform der|pem|dnskey|sshkey]"},
                {
                        {"help",        'h', 0, "show usage information"},