botan: Encode private keys as PKCS#8

Since we can now parse that encoding directly we can simplify the private
key export and stick to PKCS#8.
This commit is contained in:
Tobias Brunner 2018-08-10 09:02:26 +02:00
parent 607f10dca4
commit bd267c863f
4 changed files with 46 additions and 145 deletions

View 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*,

View 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*,

View File

@ -108,6 +108,39 @@ bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
return success;
}
/*
* 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
*/

View File

@ -64,6 +64,17 @@ const char *botan_get_hash(hash_algorithm_t hash);
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.
*