version 1.3, 2014/07/03 01:45:38 |
version 1.4, 2014/10/08 21:45:48 |
|
|
{ |
{ |
const struct keytype *kt; |
const struct keytype *kt; |
|
|
for (kt = keytypes; kt->type != -1; kt++) { |
for (kt = keytypes; kt->type != -1; kt++) { |
if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) |
if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) |
continue; |
continue; |
if (kt->name != NULL && strcmp(name, kt->name) == 0) |
if (kt->name != NULL && strcmp(name, kt->name) == 0) |
return kt->nid; |
return kt->nid; |
} |
} |
return -1; |
return -1; |
} |
} |
|
|
|
|
cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob, |
cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob, |
size_t blen) |
size_t blen) |
{ |
{ |
u_char *principals = NULL, *critical = NULL, *exts = NULL; |
struct sshbuf *principals = NULL, *crit = NULL, *exts = NULL; |
u_char *sig_key = NULL, *sig = NULL; |
u_char *sig_key = NULL, *sig = NULL; |
size_t signed_len, plen, clen, sklen, slen, kidlen, elen; |
size_t signed_len = 0, sklen = 0, slen = 0, kidlen = 0; |
struct sshbuf *tmp; |
|
char *principal; |
|
int ret = SSH_ERR_INTERNAL_ERROR; |
int ret = SSH_ERR_INTERNAL_ERROR; |
int v00 = sshkey_cert_is_legacy(key); |
int v00 = sshkey_cert_is_legacy(key); |
char **oprincipals; |
|
|
|
if ((tmp = sshbuf_new()) == NULL) |
|
return SSH_ERR_ALLOC_FAIL; |
|
|
|
/* Copy the entire key blob for verification and later serialisation */ |
/* Copy the entire key blob for verification and later serialisation */ |
if ((ret = sshbuf_put(key->cert->certblob, blob, blen)) != 0) |
if ((ret = sshbuf_put(key->cert->certblob, blob, blen)) != 0) |
return ret; |
return ret; |
|
|
elen = 0; /* Not touched for v00 certs */ |
|
principals = exts = critical = sig_key = sig = NULL; |
|
if ((!v00 && (ret = sshbuf_get_u64(b, &key->cert->serial)) != 0) || |
if ((!v00 && (ret = sshbuf_get_u64(b, &key->cert->serial)) != 0) || |
(ret = sshbuf_get_u32(b, &key->cert->type)) != 0 || |
(ret = sshbuf_get_u32(b, &key->cert->type)) != 0 || |
(ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 || |
(ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 || |
(ret = sshbuf_get_string(b, &principals, &plen)) != 0 || |
(ret = sshbuf_froms(b, &principals)) != 0 || |
(ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 || |
(ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 || |
(ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 || |
(ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 || |
(ret = sshbuf_get_string(b, &critical, &clen)) != 0 || |
(ret = sshbuf_froms(b, &crit)) != 0 || |
(!v00 && (ret = sshbuf_get_string(b, &exts, &elen)) != 0) || |
(!v00 && (ret = sshbuf_froms(b, &exts)) != 0) || |
(v00 && (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0) || |
(v00 && (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0) || |
(ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || |
(ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || |
(ret = sshbuf_get_string(b, &sig_key, &sklen)) != 0) { |
(ret = sshbuf_get_string(b, &sig_key, &sklen)) != 0) { |
|
|
goto out; |
goto out; |
} |
} |
|
|
if ((ret = sshbuf_put(tmp, principals, plen)) != 0) |
/* Parse principals section */ |
goto out; |
while (sshbuf_len(principals) > 0) { |
while (sshbuf_len(tmp) > 0) { |
char *principal = NULL; |
|
char **oprincipals = NULL; |
|
|
if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) { |
if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) { |
ret = SSH_ERR_INVALID_FORMAT; |
ret = SSH_ERR_INVALID_FORMAT; |
goto out; |
goto out; |
} |
} |
if ((ret = sshbuf_get_cstring(tmp, &principal, &plen)) != 0) { |
if ((ret = sshbuf_get_cstring(principals, &principal, |
|
NULL)) != 0) { |
ret = SSH_ERR_INVALID_FORMAT; |
ret = SSH_ERR_INVALID_FORMAT; |
goto out; |
goto out; |
} |
} |
|
|
key->cert->principals[key->cert->nprincipals++] = principal; |
key->cert->principals[key->cert->nprincipals++] = principal; |
} |
} |
|
|
sshbuf_reset(tmp); |
/* |
|
* Stash a copies of the critical options and extensions sections |
if ((ret = sshbuf_put(key->cert->critical, critical, clen)) != 0 || |
* for later use. |
(ret = sshbuf_put(tmp, critical, clen)) != 0) |
*/ |
|
if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 || |
|
(exts != NULL && |
|
(ret = sshbuf_putb(key->cert->extensions, exts)) != 0)) |
goto out; |
goto out; |
|
|
/* validate structure */ |
/* |
while (sshbuf_len(tmp) != 0) { |
* Validate critical options and extensions sections format. |
if ((ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0 || |
* NB. extensions are not present in v00 certs. |
(ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0) { |
*/ |
|
while (sshbuf_len(crit) != 0) { |
|
if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 || |
|
(ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) { |
|
sshbuf_reset(key->cert->critical); |
ret = SSH_ERR_INVALID_FORMAT; |
ret = SSH_ERR_INVALID_FORMAT; |
goto out; |
goto out; |
} |
} |
} |
} |
sshbuf_reset(tmp); |
while (exts != NULL && sshbuf_len(exts) != 0) { |
|
if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 || |
if ((ret = sshbuf_put(key->cert->extensions, exts, elen)) != 0 || |
(ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) { |
(ret = sshbuf_put(tmp, exts, elen)) != 0) |
sshbuf_reset(key->cert->extensions); |
goto out; |
|
|
|
/* validate structure */ |
|
while (sshbuf_len(tmp) != 0) { |
|
if ((ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0 || |
|
(ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0) { |
|
ret = SSH_ERR_INVALID_FORMAT; |
ret = SSH_ERR_INVALID_FORMAT; |
goto out; |
goto out; |
} |
} |
} |
} |
sshbuf_reset(tmp); |
|
|
|
|
/* Parse CA key and check signature */ |
if (sshkey_from_blob_internal(sig_key, sklen, |
if (sshkey_from_blob_internal(sig_key, sklen, |
&key->cert->signature_key, 0) != 0) { |
&key->cert->signature_key, 0) != 0) { |
ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
|
|
ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
goto out; |
goto out; |
} |
} |
|
|
if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, |
if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, |
sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0) |
sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0) |
goto out; |
goto out; |
ret = 0; |
|
|
|
|
/* Success */ |
|
ret = 0; |
out: |
out: |
sshbuf_free(tmp); |
sshbuf_free(crit); |
free(principals); |
sshbuf_free(exts); |
free(critical); |
sshbuf_free(principals); |
free(exts); |
|
free(sig_key); |
free(sig_key); |
free(sig); |
free(sig); |
return ret; |
return ret; |
|
|
const char *passphrase, const char *comment, const char *ciphername, |
const char *passphrase, const char *comment, const char *ciphername, |
int rounds) |
int rounds) |
{ |
{ |
u_char *cp, *b64 = NULL, *key = NULL, *pubkeyblob = NULL; |
u_char *cp, *key = NULL, *pubkeyblob = NULL; |
u_char salt[SALT_LEN]; |
u_char salt[SALT_LEN]; |
|
char *b64 = NULL; |
size_t i, pubkeylen, keylen, ivlen, blocksize, authlen; |
size_t i, pubkeylen, keylen, ivlen, blocksize, authlen; |
u_int check; |
u_int check; |
int r = SSH_ERR_INTERNAL_ERROR; |
int r = SSH_ERR_INTERNAL_ERROR; |
|
|
} |
} |
|
|
/* decode base64 */ |
/* decode base64 */ |
if ((r = sshbuf_b64tod(decoded, sshbuf_ptr(encoded))) != 0) |
if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0) |
goto out; |
goto out; |
|
|
/* check magic */ |
/* check magic */ |