version 1.2, 2000/04/12 09:39:10 |
version 1.3, 2000/04/26 20:56:29 |
|
|
#include <openssl/evp.h> |
#include <openssl/evp.h> |
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "key.h" |
#include "key.h" |
|
#include "dsa.h" |
|
#include "uuencode.h" |
|
|
|
#define SSH_DSS "ssh-dss" |
|
|
Key * |
Key * |
key_new(int type) |
key_new(int type) |
{ |
{ |
|
|
DSA *dsa; |
DSA *dsa; |
k = xmalloc(sizeof(*k)); |
k = xmalloc(sizeof(*k)); |
k->type = type; |
k->type = type; |
|
k->dsa = NULL; |
|
k->rsa = NULL; |
switch (k->type) { |
switch (k->type) { |
case KEY_RSA: |
case KEY_RSA: |
rsa = RSA_new(); |
rsa = RSA_new(); |
|
|
k->dsa = dsa; |
k->dsa = dsa; |
break; |
break; |
case KEY_EMPTY: |
case KEY_EMPTY: |
k->dsa = NULL; |
|
k->rsa = NULL; |
|
break; |
break; |
default: |
default: |
fatal("key_new: bad key type %d", k->type); |
fatal("key_new: bad key type %d", k->type); |
|
|
BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; |
BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; |
break; |
break; |
default: |
default: |
fatal("key_free: bad key type %d", a->type); |
fatal("key_equal: bad key type %d", a->type); |
break; |
break; |
} |
} |
return 0; |
return 0; |
|
|
key_fingerprint(Key *k) |
key_fingerprint(Key *k) |
{ |
{ |
static char retval[80]; |
static char retval[80]; |
unsigned char *buf = NULL; |
unsigned char *blob = NULL; |
int len = 0; |
int len = 0; |
int nlen, elen, plen, qlen, glen, publen; |
int nlen, elen; |
|
|
switch (k->type) { |
switch (k->type) { |
case KEY_RSA: |
case KEY_RSA: |
nlen = BN_num_bytes(k->rsa->n); |
nlen = BN_num_bytes(k->rsa->n); |
elen = BN_num_bytes(k->rsa->e); |
elen = BN_num_bytes(k->rsa->e); |
len = nlen + elen; |
len = nlen + elen; |
buf = xmalloc(len); |
blob = xmalloc(len); |
BN_bn2bin(k->rsa->n, buf); |
BN_bn2bin(k->rsa->n, blob); |
BN_bn2bin(k->rsa->e, buf + nlen); |
BN_bn2bin(k->rsa->e, blob + nlen); |
break; |
break; |
case KEY_DSA: |
case KEY_DSA: |
plen = BN_num_bytes(k->dsa->p); |
dsa_make_key_blob(k, &blob, &len); |
qlen = BN_num_bytes(k->dsa->q); |
|
glen = BN_num_bytes(k->dsa->g); |
|
publen = BN_num_bytes(k->dsa->pub_key); |
|
len = qlen + qlen + glen + publen; |
|
buf = xmalloc(len); |
|
BN_bn2bin(k->dsa->p, buf); |
|
BN_bn2bin(k->dsa->q, buf + plen); |
|
BN_bn2bin(k->dsa->g, buf + plen + qlen); |
|
BN_bn2bin(k->dsa->pub_key , buf + plen + qlen + glen); |
|
break; |
break; |
default: |
default: |
fatal("key_fingerprint: bad key type %d", k->type); |
fatal("key_fingerprint: bad key type %d", k->type); |
break; |
break; |
} |
} |
if (buf != NULL) { |
if (blob != NULL) { |
unsigned char d[16]; |
unsigned char d[16]; |
EVP_MD_CTX md; |
EVP_MD_CTX md; |
EVP_DigestInit(&md, EVP_md5()); |
EVP_DigestInit(&md, EVP_md5()); |
EVP_DigestUpdate(&md, buf, len); |
EVP_DigestUpdate(&md, blob, len); |
EVP_DigestFinal(&md, d, NULL); |
EVP_DigestFinal(&md, d, NULL); |
snprintf(retval, sizeof(retval), FPRINT, |
snprintf(retval, sizeof(retval), FPRINT, |
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], |
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], |
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); |
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); |
memset(buf, 0, len); |
memset(blob, 0, len); |
xfree(buf); |
xfree(blob); |
} |
} |
return retval; |
return retval; |
} |
} |
|
|
free(buf); |
free(buf); |
return 1; |
return 1; |
} |
} |
int |
unsigned int |
key_read(Key *ret, unsigned int bits, char **cpp) |
key_read(Key *ret, char **cpp) |
{ |
{ |
|
Key *k; |
|
unsigned int bits = 0; |
|
char *cp; |
|
int len, n; |
|
unsigned char *blob; |
|
|
|
cp = *cpp; |
|
|
switch(ret->type) { |
switch(ret->type) { |
case KEY_RSA: |
case KEY_RSA: |
|
/* Get number of bits. */ |
|
if (*cp < '0' || *cp > '9') |
|
return 0; /* Bad bit count... */ |
|
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) |
|
bits = 10 * bits + *cp - '0'; |
if (bits == 0) |
if (bits == 0) |
return 0; |
return 0; |
|
*cpp = cp; |
/* Get public exponent, public modulus. */ |
/* Get public exponent, public modulus. */ |
if (!read_bignum(cpp, ret->rsa->e)) |
if (!read_bignum(cpp, ret->rsa->e)) |
return 0; |
return 0; |
|
|
return 0; |
return 0; |
break; |
break; |
case KEY_DSA: |
case KEY_DSA: |
if (bits != 0) |
if (strncmp(cp, SSH_DSS " ", 7) != 0) |
return 0; |
return 0; |
if (!read_bignum(cpp, ret->dsa->p)) |
cp += 7; |
|
len = 2*strlen(cp); |
|
blob = xmalloc(len); |
|
n = uudecode(cp, blob, len); |
|
k = dsa_key_from_blob(blob, n); |
|
if (k == NULL) |
|
return 0; |
|
xfree(blob); |
|
if (ret->dsa != NULL) |
|
DSA_free(ret->dsa); |
|
ret->dsa = k->dsa; |
|
k->dsa = NULL; |
|
key_free(k); |
|
bits = BN_num_bits(ret->dsa->p); |
|
cp = strchr(cp, '='); |
|
if (cp == NULL) |
return 0; |
return 0; |
if (!read_bignum(cpp, ret->dsa->q)) |
*cpp = cp + 1; |
return 0; |
|
if (!read_bignum(cpp, ret->dsa->g)) |
|
return 0; |
|
if (!read_bignum(cpp, ret->dsa->pub_key)) |
|
return 0; |
|
break; |
break; |
default: |
default: |
fatal("bad key type: %d", ret->type); |
fatal("key_read: bad key type: %d", ret->type); |
break; |
break; |
} |
} |
return 1; |
return bits; |
} |
} |
int |
int |
key_write(Key *key, FILE *f) |
key_write(Key *key, FILE *f) |
|
|
error("key_write: failed for RSA key"); |
error("key_write: failed for RSA key"); |
} |
} |
} else if (key->type == KEY_DSA && key->dsa != NULL) { |
} else if (key->type == KEY_DSA && key->dsa != NULL) { |
/* bits == 0 means DSA key */ |
int len, n; |
bits = 0; |
unsigned char *blob, *uu; |
fprintf(f, "%u", bits); |
dsa_make_key_blob(key, &blob, &len); |
if (write_bignum(f, key->dsa->p) && |
uu = xmalloc(2*len); |
write_bignum(f, key->dsa->q) && |
n = uuencode(blob, len, uu); |
write_bignum(f, key->dsa->g) && |
fprintf(f, "%s %s", SSH_DSS, uu); |
write_bignum(f, key->dsa->pub_key)) { |
xfree(blob); |
success = 1; |
xfree(uu); |
} else { |
success = 1; |
error("key_write: failed for DSA key"); |
|
} |
|
} |
} |
return success; |
return success; |
} |
} |