aboutsummaryrefslogtreecommitdiffstats
path: root/sm/certreqgen.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2020-05-19 12:30:24 +0000
committerWerner Koch <[email protected]>2020-05-19 12:30:24 +0000
commit44676819f2873705b78849e7b2fd22214b691642 (patch)
treedb698a54d2c6a33d35524263d596a6679793b7e4 /sm/certreqgen.c
parentcommon: New function to extract Q from an ECC key. (diff)
downloadgnupg-44676819f2873705b78849e7b2fd22214b691642.tar.gz
gnupg-44676819f2873705b78849e7b2fd22214b691642.zip
sm: Create ECC certificates with AKI and SKI by default.
* sm/certreqgen.c (create_request): Create AKI and SKI by default. -- GnuPG-bug-id: 4098 Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'sm/certreqgen.c')
-rw-r--r--sm/certreqgen.c158
1 files changed, 127 insertions, 31 deletions
diff --git a/sm/certreqgen.c b/sm/certreqgen.c
index e54569ac8..1dd456452 100644
--- a/sm/certreqgen.c
+++ b/sm/certreqgen.c
@@ -630,7 +630,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
/* Check the optional AuthorityKeyId. */
string = get_parameter_value (para, pAUTHKEYID, 0);
- if (string)
+ if (string && strcmp (string, "none"))
{
for (s=string, i=0; hexdigitp (s); s++, i++)
;
@@ -645,7 +645,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
/* Check the optional SubjectKeyId. */
string = get_parameter_value (para, pSUBJKEYID, 0);
- if (string)
+ if (string && strcmp (string, "none"))
{
for (s=string, i=0; hexdigitp (s); s++, i++)
;
@@ -838,13 +838,22 @@ create_request (ctrl_t ctrl,
int mdalgo;
membuf_t tbsbuffer;
membuf_t *tbsmb = NULL;
+ size_t publiclen;
+ size_t sigkeylen;
+ int publicpkalgo; /* The gcrypt public key algo of the public key. */
+ int sigkeypkalgo; /* The gcrypt public key algo of the signing key. */
err = ksba_certreq_new (&cr);
if (err)
return err;
- len = gcry_sexp_canon_len (public, 0, NULL, NULL);
- if (get_pk_algo_from_canon_sexp (public, len) == GCRY_PK_EDDSA)
+ publiclen = gcry_sexp_canon_len (public, 0, NULL, NULL);
+ sigkeylen = sigkey? gcry_sexp_canon_len (sigkey, 0, NULL, NULL) : 0;
+
+ publicpkalgo = get_pk_algo_from_canon_sexp (public, publiclen);
+ sigkeypkalgo = sigkey? get_pk_algo_from_canon_sexp (public, publiclen) : 0;
+
+ if (publicpkalgo == GCRY_PK_EDDSA)
{
mdalgo = GCRY_MD_SHA512;
md = NULL; /* We sign the data and not a hash. */
@@ -957,12 +966,10 @@ create_request (ctrl_t ctrl,
}
}
-
err = ksba_certreq_set_public_key (cr, public);
if (err)
{
- log_error ("error setting the public key: %s\n",
- gpg_strerror (err));
+ log_error ("error setting the public key: %s\n", gpg_strerror (err));
rc = err;
goto leave;
}
@@ -1158,15 +1165,17 @@ create_request (ctrl_t ctrl,
given we set it to the public key to create a self-signed
certificate. */
if (!sigkey)
- sigkey = public;
+ {
+ sigkey = public;
+ sigkeylen = publiclen;
+ sigkeypkalgo = publicpkalgo;
+ }
+ /* Set the the digestinfo aka siginfo. */
{
unsigned char *siginfo;
-
- err = transform_sigval (sigkey,
- gcry_sexp_canon_len (sigkey, 0, NULL, NULL),
- mdalgo, &siginfo, NULL);
+ err = transform_sigval (sigkey, sigkeylen, mdalgo, &siginfo, NULL);
if (!err)
{
err = ksba_certreq_set_siginfo (cr, siginfo);
@@ -1181,9 +1190,12 @@ create_request (ctrl_t ctrl,
}
}
+
/* Insert the AuthorityKeyId. */
string = get_parameter_value (para, pAUTHKEYID, 0);
- if (string)
+ if (string && !strcmp (string, "none"))
+ ; /* Do not issue an AKI. */
+ else if (string)
{
char *hexbuf;
@@ -1209,20 +1221,69 @@ create_request (ctrl_t ctrl,
hexbuf[2] = 0x80; /* Context tag for an implicit Octet string. */
hexbuf[3] = len;
err = ksba_certreq_add_extension (cr, oidstr_authorityKeyIdentifier,
- 0,
- hexbuf, 4+len);
+ 0, hexbuf, 4+len);
xfree (hexbuf);
if (err)
{
- log_error ("error setting the authority-key-id: %s\n",
+ log_error ("error setting the AKI: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+ }
+ else if (publicpkalgo == GCRY_PK_EDDSA || publicpkalgo == GCRY_PK_ECC)
+ {
+ /* For EdDSA and ECC we add the public key as default identifier. */
+ const unsigned char *q;
+ size_t qlen, derlen;
+ unsigned char *der;
+
+ err = get_ecc_q_from_canon_sexp (public, publiclen, &q, &qlen);
+ if (err)
+ {
+ log_error ("error getting Q from public key: %s\n",
gpg_strerror (err));
goto leave;
}
+ if (publicpkalgo == GCRY_PK_EDDSA && qlen>32 && (qlen&1) && *q==0x40)
+ {
+ /* Skip our optional native encoding octet. */
+ q++;
+ qlen--;
+ }
+ /* FIXME: For plain ECC we should better use a compressed
+ * point. That requires an updated Libgcrypt. Without that
+ * using nistp521 won't work due to the length check below. */
+ if (qlen > 125)
+ {
+ err = gpg_error (GPG_ERR_TOO_LARGE);
+ goto leave;
+ }
+ derlen = 4 + qlen;
+ der = xtrymalloc (derlen);
+ if (!der)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ der[0] = 0x30; /* Sequence */
+ der[1] = qlen + 2;
+ der[2] = 0x80; /* Context tag for an implict Octet String. */
+ der[3] = qlen;
+ memcpy (der+4, q, qlen);
+ err = ksba_certreq_add_extension (cr, oidstr_authorityKeyIdentifier,
+ 0, der, derlen);
+ xfree (der);
+ if (err)
+ {
+ log_error ("error setting the AKI: %s\n", gpg_strerror (err));
+ goto leave;
+ }
}
/* Insert the SubjectKeyId. */
string = get_parameter_value (para, pSUBJKEYID, 0);
- if (string)
+ if (string && !strcmp (string, "none"))
+ ; /* Do not issue an SKI. */
+ else if (string)
{
char *hexbuf;
@@ -1250,10 +1311,53 @@ create_request (ctrl_t ctrl,
xfree (hexbuf);
if (err)
{
- log_error ("error setting the subject-key-id: %s\n",
+ log_error ("error setting SKI: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+ }
+ else if (sigkeypkalgo == GCRY_PK_EDDSA || sigkeypkalgo == GCRY_PK_ECC)
+ {
+ /* For EdDSA and ECC we add the public key as default identifier. */
+ const unsigned char *q;
+ size_t qlen, derlen;
+ unsigned char *der;
+
+ err = get_ecc_q_from_canon_sexp (sigkey, sigkeylen, &q, &qlen);
+ if (err)
+ {
+ log_error ("error getting Q from signature key: %s\n",
gpg_strerror (err));
goto leave;
}
+ if (sigkeypkalgo == GCRY_PK_EDDSA && qlen>32 && (qlen&1) && *q==0x40)
+ {
+ /* Skip our optional native encoding octet. */
+ q++;
+ qlen--;
+ }
+ if (qlen > 127)
+ {
+ err = gpg_error (GPG_ERR_TOO_LARGE);
+ goto leave;
+ }
+ derlen = 2 + qlen;
+ der = xtrymalloc (derlen);
+ if (!der)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ der[0] = 0x04; /* Octet String */
+ der[1] = qlen;
+ memcpy (der+2, q, qlen);
+ err = ksba_certreq_add_extension (cr, oidstr_subjectKeyIdentifier, 0,
+ der, derlen);
+ xfree (der);
+ if (err)
+ {
+ log_error ("error setting the SKI: %s\n", gpg_strerror (err));
+ goto leave;
+ }
}
/* Insert additional extensions. */
@@ -1329,7 +1433,6 @@ create_request (ctrl_t ctrl,
if (stopreason == KSBA_SR_NEED_SIG)
{
gcry_sexp_t s_pkey;
- size_t n;
unsigned char grip[20];
char hexgrip[41];
unsigned char *sigval, *newsigval;
@@ -1337,14 +1440,7 @@ create_request (ctrl_t ctrl,
void *tbsdata;
size_t tbsdatalen;
- n = gcry_sexp_canon_len (sigkey, 0, NULL, NULL);
- if (!n)
- {
- log_error ("libksba did not return a proper S-Exp\n");
- rc = gpg_error (GPG_ERR_BUG);
- goto leave;
- }
- rc = gcry_sexp_sscan (&s_pkey, NULL, (const char*)sigkey, n);
+ rc = gcry_sexp_sscan (&s_pkey, NULL, (const char*)sigkey, sigkeylen);
if (rc)
{
log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
@@ -1360,8 +1456,9 @@ create_request (ctrl_t ctrl,
gcry_sexp_release (s_pkey);
bin2hex (grip, 20, hexgrip);
- log_info ("about to sign the %s for key: &%s\n",
- certmode? "certificate":"CSR", hexgrip);
+ if (!opt.quiet)
+ log_info ("about to sign the %s for key: &%s\n",
+ certmode? "certificate":"CSR", hexgrip);
if (carddirect && !certmode)
{
@@ -1422,8 +1519,7 @@ create_request (ctrl_t ctrl,
goto leave;
}
- err = transform_sigval (sigval, siglen, mdalgo,
- &newsigval, NULL);
+ err = transform_sigval (sigval, siglen, mdalgo, &newsigval, NULL);
xfree (sigval);
if (!err)
{