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:
@@ -209,123 +209,11 @@ METHOD(private_key_t, get_fingerprint, bool,
|
|||||||
return success;
|
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,
|
METHOD(private_key_t, get_encoding, bool,
|
||||||
private_botan_ec_private_key_t *this, cred_encoding_type_t type,
|
private_botan_ec_private_key_t *this, cred_encoding_type_t type,
|
||||||
chunk_t *encoding)
|
chunk_t *encoding)
|
||||||
{
|
{
|
||||||
switch (type)
|
return botan_get_privkey_encoding(this->key, type, encoding);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(private_key_t, get_ref, private_key_t*,
|
METHOD(private_key_t, get_ref, private_key_t*,
|
||||||
|
|||||||
@@ -257,38 +257,7 @@ METHOD(private_key_t, get_encoding, bool,
|
|||||||
private_botan_rsa_private_key_t *this, cred_encoding_type_t type,
|
private_botan_rsa_private_key_t *this, cred_encoding_type_t type,
|
||||||
chunk_t *encoding)
|
chunk_t *encoding)
|
||||||
{
|
{
|
||||||
switch (type)
|
return botan_get_privkey_encoding(this->key, type, encoding);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(private_key_t, get_ref, private_key_t*,
|
METHOD(private_key_t, get_ref, private_key_t*,
|
||||||
|
|||||||
@@ -108,6 +108,39 @@ bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
|
|||||||
return success;
|
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
|
* Described in header
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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,
|
bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
|
||||||
chunk_t *encoding);
|
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.
|
* Get the fingerprint of a botan_pubkey_t.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user