version 1.108, 2013/12/06 13:34:54 |
version 1.109, 2013/12/06 13:39:49 |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
|
|
#include <openssl/evp.h> |
#include <openssl/evp.h> |
|
#include "crypto_api.h" |
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <string.h> |
#include <string.h> |
|
|
k->dsa = NULL; |
k->dsa = NULL; |
k->rsa = NULL; |
k->rsa = NULL; |
k->cert = NULL; |
k->cert = NULL; |
|
k->ed25519_sk = NULL; |
|
k->ed25519_pk = NULL; |
switch (k->type) { |
switch (k->type) { |
case KEY_RSA1: |
case KEY_RSA1: |
case KEY_RSA: |
case KEY_RSA: |
|
|
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
/* Cannot do anything until we know the group */ |
/* Cannot do anything until we know the group */ |
break; |
break; |
|
case KEY_ED25519: |
|
case KEY_ED25519_CERT: |
|
/* no need to prealloc */ |
|
break; |
case KEY_UNSPEC: |
case KEY_UNSPEC: |
break; |
break; |
default: |
default: |
|
|
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
/* Cannot do anything until we know the group */ |
/* Cannot do anything until we know the group */ |
break; |
break; |
|
case KEY_ED25519: |
|
case KEY_ED25519_CERT: |
|
/* no need to prealloc */ |
|
break; |
case KEY_UNSPEC: |
case KEY_UNSPEC: |
break; |
break; |
default: |
default: |
|
|
EC_KEY_free(k->ecdsa); |
EC_KEY_free(k->ecdsa); |
k->ecdsa = NULL; |
k->ecdsa = NULL; |
break; |
break; |
|
case KEY_ED25519: |
|
case KEY_ED25519_CERT: |
|
if (k->ed25519_pk) { |
|
memset(k->ed25519_pk, 0, ED25519_PK_SZ); |
|
free(k->ed25519_pk); |
|
k->ed25519_pk = NULL; |
|
} |
|
if (k->ed25519_sk) { |
|
memset(k->ed25519_sk, 0, ED25519_SK_SZ); |
|
free(k->ed25519_sk); |
|
k->ed25519_sk = NULL; |
|
} |
|
break; |
case KEY_UNSPEC: |
case KEY_UNSPEC: |
break; |
break; |
default: |
default: |
|
|
} |
} |
BN_CTX_free(bnctx); |
BN_CTX_free(bnctx); |
return 1; |
return 1; |
|
case KEY_ED25519: |
|
case KEY_ED25519_CERT: |
|
return a->ed25519_pk != NULL && b->ed25519_pk != NULL && |
|
memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0; |
default: |
default: |
fatal("key_equal: bad key type %d", a->type); |
fatal("key_equal: bad key type %d", a->type); |
} |
} |
|
|
case KEY_DSA: |
case KEY_DSA: |
case KEY_ECDSA: |
case KEY_ECDSA: |
case KEY_RSA: |
case KEY_RSA: |
|
case KEY_ED25519: |
key_to_blob(k, &blob, &len); |
key_to_blob(k, &blob, &len); |
break; |
break; |
case KEY_DSA_CERT_V00: |
case KEY_DSA_CERT_V00: |
|
|
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
|
case KEY_ED25519_CERT: |
/* We want a fingerprint of the _key_ not of the cert */ |
/* We want a fingerprint of the _key_ not of the cert */ |
to_blob(k, &blob, &len, 1); |
to_blob(k, &blob, &len, 1); |
break; |
break; |
|
|
case KEY_RSA: |
case KEY_RSA: |
case KEY_DSA: |
case KEY_DSA: |
case KEY_ECDSA: |
case KEY_ECDSA: |
|
case KEY_ED25519: |
case KEY_DSA_CERT_V00: |
case KEY_DSA_CERT_V00: |
case KEY_RSA_CERT_V00: |
case KEY_RSA_CERT_V00: |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
|
case KEY_ED25519_CERT: |
space = strchr(cp, ' '); |
space = strchr(cp, ' '); |
if (space == NULL) { |
if (space == NULL) { |
debug3("key_read: missing whitespace"); |
debug3("key_read: missing whitespace"); |
|
|
key_dump_ec_key(ret->ecdsa); |
key_dump_ec_key(ret->ecdsa); |
#endif |
#endif |
} |
} |
|
if (key_type_plain(ret->type) == KEY_ED25519) { |
|
free(ret->ed25519_pk); |
|
ret->ed25519_pk = k->ed25519_pk; |
|
k->ed25519_pk = NULL; |
|
#ifdef DEBUG_PK |
|
/* XXX */ |
|
#endif |
|
} |
success = 1; |
success = 1; |
/*XXXX*/ |
/*XXXX*/ |
key_free(k); |
key_free(k); |
|
|
if (key->ecdsa == NULL) |
if (key->ecdsa == NULL) |
return 0; |
return 0; |
break; |
break; |
|
case KEY_ED25519: |
|
case KEY_ED25519_CERT: |
|
if (key->ed25519_pk == NULL) |
|
return 0; |
|
break; |
case KEY_RSA: |
case KEY_RSA: |
case KEY_RSA_CERT_V00: |
case KEY_RSA_CERT_V00: |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
|
|
{ NULL, "RSA1", KEY_RSA1, 0, 0 }, |
{ NULL, "RSA1", KEY_RSA1, 0, 0 }, |
{ "ssh-rsa", "RSA", KEY_RSA, 0, 0 }, |
{ "ssh-rsa", "RSA", KEY_RSA, 0, 0 }, |
{ "ssh-dss", "DSA", KEY_DSA, 0, 0 }, |
{ "ssh-dss", "DSA", KEY_DSA, 0, 0 }, |
|
{ "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 }, |
{ "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 }, |
{ "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 }, |
{ "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 }, |
{ "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 }, |
{ "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 }, |
{ "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 }, |
|
|
KEY_RSA_CERT_V00, 0, 1 }, |
KEY_RSA_CERT_V00, 0, 1 }, |
{ "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", |
{ "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", |
KEY_DSA_CERT_V00, 0, 1 }, |
KEY_DSA_CERT_V00, 0, 1 }, |
|
{ "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", |
|
KEY_ED25519_CERT, 0, 1 }, |
{ NULL, NULL, -1, -1, 0 } |
{ NULL, NULL, -1, -1, 0 } |
}; |
}; |
|
|
|
|
} |
} |
|
|
char * |
char * |
key_alg_list(void) |
key_alg_list(int certs_only, int plain_only) |
{ |
{ |
char *ret = NULL; |
char *ret = NULL; |
size_t nlen, rlen = 0; |
size_t nlen, rlen = 0; |
|
|
for (kt = keytypes; kt->type != -1; kt++) { |
for (kt = keytypes; kt->type != -1; kt++) { |
if (kt->name == NULL) |
if (kt->name == NULL) |
continue; |
continue; |
|
if ((certs_only && !kt->cert) || (plain_only && kt->cert)) |
|
continue; |
if (ret != NULL) |
if (ret != NULL) |
ret[rlen++] = '\n'; |
ret[rlen++] = '\n'; |
nlen = strlen(kt->name); |
nlen = strlen(kt->name); |
|
|
case KEY_DSA_CERT_V00: |
case KEY_DSA_CERT_V00: |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
return BN_num_bits(k->dsa->p); |
return BN_num_bits(k->dsa->p); |
|
case KEY_ED25519: |
|
return 256; /* XXX */ |
case KEY_ECDSA: |
case KEY_ECDSA: |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
return key_curve_nid_to_bits(k->ecdsa_nid); |
return key_curve_nid_to_bits(k->ecdsa_nid); |
|
|
case KEY_RSA1: |
case KEY_RSA1: |
k->rsa = rsa_generate_private_key(bits); |
k->rsa = rsa_generate_private_key(bits); |
break; |
break; |
|
case KEY_ED25519: |
|
k->ed25519_pk = xmalloc(ED25519_PK_SZ); |
|
k->ed25519_sk = xmalloc(ED25519_SK_SZ); |
|
crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk); |
|
break; |
case KEY_RSA_CERT_V00: |
case KEY_RSA_CERT_V00: |
case KEY_DSA_CERT_V00: |
case KEY_DSA_CERT_V00: |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
|
|
(BN_copy(n->rsa->e, k->rsa->e) == NULL)) |
(BN_copy(n->rsa->e, k->rsa->e) == NULL)) |
fatal("key_from_private: BN_copy failed"); |
fatal("key_from_private: BN_copy failed"); |
break; |
break; |
|
case KEY_ED25519: |
|
case KEY_ED25519_CERT: |
|
n = key_new(k->type); |
|
if (k->ed25519_pk != NULL) { |
|
n->ed25519_pk = xmalloc(ED25519_PK_SZ); |
|
memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); |
|
} |
|
break; |
default: |
default: |
fatal("key_from_private: unknown type %d", k->type); |
fatal("key_from_private: unknown type %d", k->type); |
break; |
break; |
|
|
{ |
{ |
Buffer b; |
Buffer b; |
int rlen, type, nid = -1; |
int rlen, type, nid = -1; |
|
u_int len; |
char *ktype = NULL, *curve = NULL; |
char *ktype = NULL, *curve = NULL; |
|
u_char *pk = NULL; |
Key *key = NULL; |
Key *key = NULL; |
EC_POINT *q = NULL; |
EC_POINT *q = NULL; |
|
|
|
|
key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q); |
key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q); |
#endif |
#endif |
break; |
break; |
|
case KEY_ED25519_CERT: |
|
(void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ |
|
/* FALLTHROUGH */ |
|
case KEY_ED25519: |
|
if ((pk = buffer_get_string_ret(&b, &len)) == NULL) { |
|
error("key_from_blob: can't read ed25519 key"); |
|
goto badkey; |
|
} |
|
if (len != ED25519_PK_SZ) { |
|
error("key_from_blob: ed25519 len %d != %d", |
|
len, ED25519_PK_SZ); |
|
goto badkey; |
|
} |
|
key = key_new(type); |
|
key->ed25519_pk = pk; |
|
pk = NULL; |
|
break; |
case KEY_UNSPEC: |
case KEY_UNSPEC: |
key = key_new(type); |
key = key_new(type); |
break; |
break; |
|
|
out: |
out: |
free(ktype); |
free(ktype); |
free(curve); |
free(curve); |
|
free(pk); |
if (q != NULL) |
if (q != NULL) |
EC_POINT_free(q); |
EC_POINT_free(q); |
buffer_free(&b); |
buffer_free(&b); |
|
|
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
|
case KEY_ED25519_CERT: |
/* Use the existing blob */ |
/* Use the existing blob */ |
buffer_append(&b, buffer_ptr(&key->cert->certblob), |
buffer_append(&b, buffer_ptr(&key->cert->certblob), |
buffer_len(&key->cert->certblob)); |
buffer_len(&key->cert->certblob)); |
|
|
buffer_put_bignum2(&b, key->rsa->e); |
buffer_put_bignum2(&b, key->rsa->e); |
buffer_put_bignum2(&b, key->rsa->n); |
buffer_put_bignum2(&b, key->rsa->n); |
break; |
break; |
|
case KEY_ED25519: |
|
buffer_put_cstring(&b, |
|
key_ssh_name_from_type_nid(type, key->ecdsa_nid)); |
|
buffer_put_string(&b, key->ed25519_pk, ED25519_PK_SZ); |
|
break; |
default: |
default: |
error("key_to_blob: unsupported key type %d", key->type); |
error("key_to_blob: unsupported key type %d", key->type); |
buffer_free(&b); |
buffer_free(&b); |
|
|
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
case KEY_RSA: |
case KEY_RSA: |
return ssh_rsa_sign(key, sigp, lenp, data, datalen); |
return ssh_rsa_sign(key, sigp, lenp, data, datalen); |
|
case KEY_ED25519: |
|
case KEY_ED25519_CERT: |
|
return ssh_ed25519_sign(key, sigp, lenp, data, datalen); |
default: |
default: |
error("key_sign: invalid key type %d", key->type); |
error("key_sign: invalid key type %d", key->type); |
return -1; |
return -1; |
|
|
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
case KEY_RSA: |
case KEY_RSA: |
return ssh_rsa_verify(key, signature, signaturelen, data, datalen); |
return ssh_rsa_verify(key, signature, signaturelen, data, datalen); |
|
case KEY_ED25519: |
|
case KEY_ED25519_CERT: |
|
return ssh_ed25519_verify(key, signature, signaturelen, data, datalen); |
default: |
default: |
error("key_verify: invalid key type %d", key->type); |
error("key_verify: invalid key type %d", key->type); |
return -1; |
return -1; |
|
|
pk->dsa = NULL; |
pk->dsa = NULL; |
pk->ecdsa = NULL; |
pk->ecdsa = NULL; |
pk->rsa = NULL; |
pk->rsa = NULL; |
|
pk->ed25519_pk = NULL; |
|
pk->ed25519_sk = NULL; |
|
|
switch (k->type) { |
switch (k->type) { |
case KEY_RSA_CERT_V00: |
case KEY_RSA_CERT_V00: |
|
|
EC_KEY_get0_public_key(k->ecdsa)) != 1) |
EC_KEY_get0_public_key(k->ecdsa)) != 1) |
fatal("key_demote: EC_KEY_set_public_key failed"); |
fatal("key_demote: EC_KEY_set_public_key failed"); |
break; |
break; |
|
case KEY_ED25519_CERT: |
|
key_cert_copy(k, pk); |
|
/* FALLTHROUGH */ |
|
case KEY_ED25519: |
|
if (k->ed25519_pk != NULL) { |
|
pk->ed25519_pk = xmalloc(ED25519_PK_SZ); |
|
memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); |
|
} |
|
break; |
default: |
default: |
fatal("key_free: bad key type %d", k->type); |
fatal("key_demote: bad key type %d", k->type); |
break; |
break; |
} |
} |
|
|
|
|
return KEY_DSA; |
return KEY_DSA; |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
return KEY_ECDSA; |
return KEY_ECDSA; |
|
case KEY_ED25519_CERT: |
|
return KEY_ED25519; |
default: |
default: |
return type; |
return type; |
} |
} |
|
|
k->cert = cert_new(); |
k->cert = cert_new(); |
k->type = KEY_ECDSA_CERT; |
k->type = KEY_ECDSA_CERT; |
return 0; |
return 0; |
|
case KEY_ED25519: |
|
if (legacy) |
|
fatal("%s: legacy ED25519 certificates are not " |
|
"supported", __func__); |
|
k->cert = cert_new(); |
|
k->type = KEY_ED25519_CERT; |
|
return 0; |
default: |
default: |
error("%s: key has incorrect type %s", __func__, key_type(k)); |
error("%s: key has incorrect type %s", __func__, key_type(k)); |
return -1; |
return -1; |
|
|
int |
int |
key_drop_cert(Key *k) |
key_drop_cert(Key *k) |
{ |
{ |
switch (k->type) { |
if (!key_type_is_cert(k->type)) { |
case KEY_RSA_CERT_V00: |
|
case KEY_RSA_CERT: |
|
cert_free(k->cert); |
|
k->type = KEY_RSA; |
|
return 0; |
|
case KEY_DSA_CERT_V00: |
|
case KEY_DSA_CERT: |
|
cert_free(k->cert); |
|
k->type = KEY_DSA; |
|
return 0; |
|
case KEY_ECDSA_CERT: |
|
cert_free(k->cert); |
|
k->type = KEY_ECDSA; |
|
return 0; |
|
default: |
|
error("%s: key has incorrect type %s", __func__, key_type(k)); |
error("%s: key has incorrect type %s", __func__, key_type(k)); |
return -1; |
return -1; |
} |
} |
|
cert_free(k->cert); |
|
k->type = key_type_plain(k->type); |
|
return 0; |
} |
} |
|
|
/* |
/* Sign a certified key, (re-)generating the signed certblob. */ |
* Sign a KEY_RSA_CERT, KEY_DSA_CERT or KEY_ECDSA_CERT, (re-)generating |
|
* the signed certblob |
|
*/ |
|
int |
int |
key_certify(Key *k, Key *ca) |
key_certify(Key *k, Key *ca) |
{ |
{ |
|
|
} |
} |
|
|
if (ca->type != KEY_RSA && ca->type != KEY_DSA && |
if (ca->type != KEY_RSA && ca->type != KEY_DSA && |
ca->type != KEY_ECDSA) { |
ca->type != KEY_ECDSA && ca->type != KEY_ED25519) { |
error("%s: CA key has unsupported type %s", __func__, |
error("%s: CA key has unsupported type %s", __func__, |
key_type(ca)); |
key_type(ca)); |
return -1; |
return -1; |
|
|
buffer_put_bignum2(&k->cert->certblob, k->rsa->e); |
buffer_put_bignum2(&k->cert->certblob, k->rsa->e); |
buffer_put_bignum2(&k->cert->certblob, k->rsa->n); |
buffer_put_bignum2(&k->cert->certblob, k->rsa->n); |
break; |
break; |
|
case KEY_ED25519_CERT: |
|
buffer_put_string(&k->cert->certblob, |
|
k->ed25519_pk, ED25519_PK_SZ); |
|
break; |
default: |
default: |
error("%s: key has incorrect type %s", __func__, key_type(k)); |
error("%s: key has incorrect type %s", __func__, key_type(k)); |
buffer_clear(&k->cert->certblob); |
buffer_clear(&k->cert->certblob); |
|
|
buffer_len(&key->cert->certblob)); |
buffer_len(&key->cert->certblob)); |
buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa)); |
buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa)); |
break; |
break; |
|
case KEY_ED25519: |
|
buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ); |
|
buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ); |
|
break; |
|
case KEY_ED25519_CERT: |
|
if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) |
|
fatal("%s: no cert/certblob", __func__); |
|
buffer_put_string(b, buffer_ptr(&key->cert->certblob), |
|
buffer_len(&key->cert->certblob)); |
|
buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ); |
|
buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ); |
|
break; |
} |
} |
} |
} |
|
|
|
|
BIGNUM *exponent; |
BIGNUM *exponent; |
EC_POINT *q; |
EC_POINT *q; |
u_char *cert; |
u_char *cert; |
u_int len; |
u_int len, pklen, sklen; |
int type; |
int type; |
|
|
type_name = buffer_get_string(blob, NULL); |
type_name = buffer_get_string(blob, NULL); |
|
|
buffer_get_bignum2(blob, k->rsa->iqmp); |
buffer_get_bignum2(blob, k->rsa->iqmp); |
buffer_get_bignum2(blob, k->rsa->p); |
buffer_get_bignum2(blob, k->rsa->p); |
buffer_get_bignum2(blob, k->rsa->q); |
buffer_get_bignum2(blob, k->rsa->q); |
|
break; |
|
case KEY_ED25519: |
|
k = key_new_private(type); |
|
k->ed25519_pk = buffer_get_string(blob, &pklen); |
|
k->ed25519_sk = buffer_get_string(blob, &sklen); |
|
if (pklen != ED25519_PK_SZ) |
|
fatal("%s: ed25519 pklen %d != %d", |
|
__func__, pklen, ED25519_PK_SZ); |
|
if (sklen != ED25519_SK_SZ) |
|
fatal("%s: ed25519 sklen %d != %d", |
|
__func__, sklen, ED25519_SK_SZ); |
|
break; |
|
case KEY_ED25519_CERT: |
|
cert = buffer_get_string(blob, &len); |
|
if ((k = key_from_blob(cert, len)) == NULL) |
|
fatal("Certificate parse failed"); |
|
free(cert); |
|
key_add_private(k); |
|
k->ed25519_pk = buffer_get_string(blob, &pklen); |
|
k->ed25519_sk = buffer_get_string(blob, &sklen); |
|
if (pklen != ED25519_PK_SZ) |
|
fatal("%s: ed25519 pklen %d != %d", |
|
__func__, pklen, ED25519_PK_SZ); |
|
if (sklen != ED25519_SK_SZ) |
|
fatal("%s: ed25519 sklen %d != %d", |
|
__func__, sklen, ED25519_SK_SZ); |
break; |
break; |
default: |
default: |
free(type_name); |
free(type_name); |