Skip to content

Commit

Permalink
pivy-ca: include SPKI extension on subordinate CAs
Browse files Browse the repository at this point in the history
  • Loading branch information
arekinath committed Mar 25, 2024
1 parent 2d20b9e commit 1c50961
Showing 1 changed file with 88 additions and 48 deletions.
136 changes: 88 additions & 48 deletions piv-certs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,54 @@ cert_var_eval_into(struct cert_var *cv, struct sshbuf *buf)
return (ERRF_OK);
}

static errf_t *
pkey_key_id(EVP_PKEY *pkey, ASN1_OCTET_STRING **out)
{
errf_t *err;
int rc;
ASN1_OCTET_STRING *kid = NULL;
X509_PUBKEY *xpub = NULL;
const uint8_t *pkdata;
uint8_t *pkhash = NULL;
uint pkhlen;
int pklen;

rc = X509_PUBKEY_set(&xpub, pkey);
if (rc != 1) {
make_sslerrf(err, "X509_PUBKEY_set", "allocating keyid");
goto out;
}

rc = X509_PUBKEY_get0_param(NULL, &pkdata, &pklen, NULL, xpub);
VERIFY(rc == 1);

pkhlen = SHA_DIGEST_LENGTH;
pkhash = malloc(pkhlen);
VERIFY(pkhash != NULL);
rc = EVP_Digest(pkdata, pklen, pkhash, &pkhlen, EVP_sha1(), NULL);
if (rc != 1) {
make_sslerrf(err, "EVP_Digest", "allocating keyid");
goto out;
}

kid = ASN1_OCTET_STRING_new();
if (kid == NULL) {
make_sslerrf(err, "ASN1_OCTET_STRING_new", "allocating keyid");
goto out;
}
ASN1_STRING_set(kid, pkhash, pkhlen);

*out = kid;
kid = NULL;
err = ERRF_OK;

out:
free(pkhash);
X509_PUBKEY_free(xpub);
ASN1_OCTET_STRING_free(kid);
return (err);
}

static errf_t *
populate_common(struct cert_var_scope *cs, X509 *cert, char *basic, char *ku,
char *eku)
Expand Down Expand Up @@ -1980,6 +2028,9 @@ populate_ca(struct cert_var_scope *cs, X509 *cert)
char basic[128];
char *eku = NULL;
CONF *config = NULL;
EVP_PKEY *pubkey = NULL;
ASN1_OCTET_STRING *kid = NULL;
int rc;

OPENSSL_load_builtin_modules();

Expand Down Expand Up @@ -2029,9 +2080,26 @@ populate_ca(struct cert_var_scope *cs, X509 *cert)
errf_free(err);
}

pubkey = X509_get_pubkey(cert);
if (pubkey != NULL) {
err = pkey_key_id(pubkey, &kid);
if (err != ERRF_OK)
goto out;

rc = X509_add1_ext_i2d(cert, NID_subject_key_identifier, kid, 0,
X509V3_ADD_REPLACE);
if (rc != 1) {
make_sslerrf(err, "X509_add1_ext_i2d", "adding subject "
"key id");
goto out;
}
}

err = ERRF_OK;

out:
ASN1_OCTET_STRING_free(kid);
EVP_PKEY_free(pubkey);
free(namecons);
free(pathlen);
free(eku);
Expand Down Expand Up @@ -2501,6 +2569,9 @@ rpopulate_ca(struct cert_var_scope *cs, X509_REQ *req)
char basic[128];
char *eku = NULL;
CONF *config = NULL;
EVP_PKEY *pubkey = NULL;
ASN1_OCTET_STRING *kid = NULL;
int rc;

exts = sk_X509_EXTENSION_new_null();
VERIFY(exts != NULL);
Expand Down Expand Up @@ -2549,12 +2620,29 @@ rpopulate_ca(struct cert_var_scope *cs, X509_REQ *req)
errf_free(err);
}

pubkey = X509_REQ_get_pubkey(req);
if (pubkey != NULL) {
err = pkey_key_id(pubkey, &kid);
if (err != ERRF_OK)
goto out;

rc = X509V3_add1_i2d(&exts, NID_subject_key_identifier, kid,
0, X509V3_ADD_REPLACE);
if (rc != 1) {
make_sslerrf(err, "X509V3_add1_i2d", "generating "
" subject key id");
goto out;
}
}

VERIFY(X509_REQ_add_extensions(req, exts) == 1);
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);

err = ERRF_OK;

out:
ASN1_OCTET_STRING_free(kid);
EVP_PKEY_free(pubkey);
free(namecons);
free(pathlen);
free(eku);
Expand Down Expand Up @@ -2664,54 +2752,6 @@ set_pkey_from_sshkey(struct sshkey *pubkey, struct piv_token *tkn,
return (err);
}

static errf_t *
pkey_key_id(EVP_PKEY *pkey, ASN1_OCTET_STRING **out)
{
errf_t *err;
int rc;
ASN1_OCTET_STRING *kid = NULL;
X509_PUBKEY *xpub = NULL;
const uint8_t *pkdata;
uint8_t *pkhash = NULL;
uint pkhlen;
int pklen;

rc = X509_PUBKEY_set(&xpub, pkey);
if (rc != 1) {
make_sslerrf(err, "X509_PUBKEY_set", "allocating keyid");
goto out;
}

rc = X509_PUBKEY_get0_param(NULL, &pkdata, &pklen, NULL, xpub);
VERIFY(rc == 1);

pkhlen = SHA_DIGEST_LENGTH;
pkhash = malloc(pkhlen);
VERIFY(pkhash != NULL);
rc = EVP_Digest(pkdata, pklen, pkhash, &pkhlen, EVP_sha1(), NULL);
if (rc != 1) {
make_sslerrf(err, "EVP_Digest", "allocating keyid");
goto out;
}

kid = ASN1_OCTET_STRING_new();
if (kid == NULL) {
make_sslerrf(err, "ASN1_OCTET_STRING_new", "allocating keyid");
goto out;
}
ASN1_STRING_set(kid, pkhash, pkhlen);

*out = kid;
kid = NULL;
err = ERRF_OK;

out:
free(pkhash);
X509_PUBKEY_free(xpub);
ASN1_OCTET_STRING_free(kid);
return (err);
}

errf_t *
piv_selfsign_cert(struct piv_token *tkn, struct piv_slot *slot,
struct sshkey *pubkey, X509 *cert)
Expand Down

0 comments on commit 1c50961

Please sign in to comment.