Store and parse BLISS private and public keys in DER and PEM format
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.
This commit is contained in:
parent
37bfe44358
commit
56009f2001
|
@ -212,7 +212,7 @@
|
|||
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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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>
|
||||
|
@ -26,6 +29,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.
|
||||
*/
|
||||
|
@ -40,6 +55,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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -561,25 +636,108 @@ bliss_private_key_t *bliss_private_key_gen(key_type_t type, va_list args)
|
|||
return success ? &this->public : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,11 @@
|
|||
*/
|
||||
|
||||
#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, ¶m);
|
||||
if (oid != OID_BLISS_PUBLICKEY)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
if (!asn1_parse_simple_object(¶m, 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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -32,9 +32,12 @@
|
|||
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"},
|
||||
|
|
|
@ -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"},
|
||||
|
|
Loading…
Reference in New Issue