mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
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 <wk@gnupg.org>
This commit is contained in:
parent
3cd9dac7e0
commit
44676819f2
@ -1099,10 +1099,12 @@ General Parameters:
|
|||||||
@item Key-Type: @var{algo}
|
@item Key-Type: @var{algo}
|
||||||
Starts a new parameter block by giving the type of the primary
|
Starts a new parameter block by giving the type of the primary
|
||||||
key. The algorithm must be capable of signing. This is a required
|
key. The algorithm must be capable of signing. This is a required
|
||||||
parameter. The only supported value for @var{algo} is @samp{rsa}.
|
parameter. The supported values for @var{algo} are @samp{rsa},
|
||||||
|
@samp{ecdsa}, and @samp{eddsa}.
|
||||||
|
|
||||||
@item Key-Length: @var{nbits}
|
@item Key-Length: @var{nbits}
|
||||||
The requested length of a generated key in bits. Defaults to 3072.
|
The requested length of a generated key in bits. Defaults to
|
||||||
|
3072. The value is ignored for ECC algorithms.
|
||||||
|
|
||||||
@item Key-Grip: @var{hexstring}
|
@item Key-Grip: @var{hexstring}
|
||||||
This is optional and used to generate a CSR or certificate for an
|
This is optional and used to generate a CSR or certificate for an
|
||||||
@ -1175,6 +1177,20 @@ algorithms are: @samp{sha1}, @samp{sha256}, @samp{sha384} and
|
|||||||
@samp{sha512}; they may also be specified with uppercase letters. The
|
@samp{sha512}; they may also be specified with uppercase letters. The
|
||||||
default is @samp{sha256}.
|
default is @samp{sha256}.
|
||||||
|
|
||||||
|
@item Authority-Key-Id: @var{hexstring}
|
||||||
|
Insert the decoded value of @var{hexstring} as authorityKeyIdentifier.
|
||||||
|
If this is not given and an ECC algorithm is used the public part of
|
||||||
|
the certified public key is used as authorityKeyIdentifier. To
|
||||||
|
inhibit any authorityKeyIdentifier use the special value @code{none}
|
||||||
|
for @var{hexstring}.
|
||||||
|
|
||||||
|
@item Subject-Key-Id: @var{hexstring}
|
||||||
|
Insert the decoded value of @var{hexstring} as subjectKeyIdentifier.
|
||||||
|
If this is not given and an ECC algorithm is used the public part of
|
||||||
|
the signing key is used as authorityKeyIdentifier. To inhibit any
|
||||||
|
subjectKeyIdentifier use the special value @code{none} for
|
||||||
|
@var{hexstring}.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@c *******************************************
|
@c *******************************************
|
||||||
|
158
sm/certreqgen.c
158
sm/certreqgen.c
@ -630,7 +630,7 @@ proc_parameters (ctrl_t ctrl, struct para_data_s *para,
|
|||||||
|
|
||||||
/* Check the optional AuthorityKeyId. */
|
/* Check the optional AuthorityKeyId. */
|
||||||
string = get_parameter_value (para, pAUTHKEYID, 0);
|
string = get_parameter_value (para, pAUTHKEYID, 0);
|
||||||
if (string)
|
if (string && strcmp (string, "none"))
|
||||||
{
|
{
|
||||||
for (s=string, i=0; hexdigitp (s); s++, i++)
|
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. */
|
/* Check the optional SubjectKeyId. */
|
||||||
string = get_parameter_value (para, pSUBJKEYID, 0);
|
string = get_parameter_value (para, pSUBJKEYID, 0);
|
||||||
if (string)
|
if (string && strcmp (string, "none"))
|
||||||
{
|
{
|
||||||
for (s=string, i=0; hexdigitp (s); s++, i++)
|
for (s=string, i=0; hexdigitp (s); s++, i++)
|
||||||
;
|
;
|
||||||
@ -838,13 +838,22 @@ create_request (ctrl_t ctrl,
|
|||||||
int mdalgo;
|
int mdalgo;
|
||||||
membuf_t tbsbuffer;
|
membuf_t tbsbuffer;
|
||||||
membuf_t *tbsmb = NULL;
|
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);
|
err = ksba_certreq_new (&cr);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
len = gcry_sexp_canon_len (public, 0, NULL, NULL);
|
publiclen = gcry_sexp_canon_len (public, 0, NULL, NULL);
|
||||||
if (get_pk_algo_from_canon_sexp (public, len) == GCRY_PK_EDDSA)
|
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;
|
mdalgo = GCRY_MD_SHA512;
|
||||||
md = NULL; /* We sign the data and not a hash. */
|
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);
|
err = ksba_certreq_set_public_key (cr, public);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error ("error setting the public key: %s\n",
|
log_error ("error setting the public key: %s\n", gpg_strerror (err));
|
||||||
gpg_strerror (err));
|
|
||||||
rc = err;
|
rc = err;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -1158,15 +1165,17 @@ create_request (ctrl_t ctrl,
|
|||||||
given we set it to the public key to create a self-signed
|
given we set it to the public key to create a self-signed
|
||||||
certificate. */
|
certificate. */
|
||||||
if (!sigkey)
|
if (!sigkey)
|
||||||
sigkey = public;
|
{
|
||||||
|
sigkey = public;
|
||||||
|
sigkeylen = publiclen;
|
||||||
|
sigkeypkalgo = publicpkalgo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the the digestinfo aka siginfo. */
|
||||||
{
|
{
|
||||||
unsigned char *siginfo;
|
unsigned char *siginfo;
|
||||||
|
|
||||||
|
err = transform_sigval (sigkey, sigkeylen, mdalgo, &siginfo, NULL);
|
||||||
err = transform_sigval (sigkey,
|
|
||||||
gcry_sexp_canon_len (sigkey, 0, NULL, NULL),
|
|
||||||
mdalgo, &siginfo, NULL);
|
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
err = ksba_certreq_set_siginfo (cr, siginfo);
|
err = ksba_certreq_set_siginfo (cr, siginfo);
|
||||||
@ -1181,9 +1190,12 @@ create_request (ctrl_t ctrl,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Insert the AuthorityKeyId. */
|
/* Insert the AuthorityKeyId. */
|
||||||
string = get_parameter_value (para, pAUTHKEYID, 0);
|
string = get_parameter_value (para, pAUTHKEYID, 0);
|
||||||
if (string)
|
if (string && !strcmp (string, "none"))
|
||||||
|
; /* Do not issue an AKI. */
|
||||||
|
else if (string)
|
||||||
{
|
{
|
||||||
char *hexbuf;
|
char *hexbuf;
|
||||||
|
|
||||||
@ -1209,20 +1221,69 @@ create_request (ctrl_t ctrl,
|
|||||||
hexbuf[2] = 0x80; /* Context tag for an implicit Octet string. */
|
hexbuf[2] = 0x80; /* Context tag for an implicit Octet string. */
|
||||||
hexbuf[3] = len;
|
hexbuf[3] = len;
|
||||||
err = ksba_certreq_add_extension (cr, oidstr_authorityKeyIdentifier,
|
err = ksba_certreq_add_extension (cr, oidstr_authorityKeyIdentifier,
|
||||||
0,
|
0, hexbuf, 4+len);
|
||||||
hexbuf, 4+len);
|
|
||||||
xfree (hexbuf);
|
xfree (hexbuf);
|
||||||
if (err)
|
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));
|
gpg_strerror (err));
|
||||||
goto leave;
|
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. */
|
/* Insert the SubjectKeyId. */
|
||||||
string = get_parameter_value (para, pSUBJKEYID, 0);
|
string = get_parameter_value (para, pSUBJKEYID, 0);
|
||||||
if (string)
|
if (string && !strcmp (string, "none"))
|
||||||
|
; /* Do not issue an SKI. */
|
||||||
|
else if (string)
|
||||||
{
|
{
|
||||||
char *hexbuf;
|
char *hexbuf;
|
||||||
|
|
||||||
@ -1250,10 +1311,53 @@ create_request (ctrl_t ctrl,
|
|||||||
xfree (hexbuf);
|
xfree (hexbuf);
|
||||||
if (err)
|
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));
|
gpg_strerror (err));
|
||||||
goto leave;
|
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. */
|
/* Insert additional extensions. */
|
||||||
@ -1329,7 +1433,6 @@ create_request (ctrl_t ctrl,
|
|||||||
if (stopreason == KSBA_SR_NEED_SIG)
|
if (stopreason == KSBA_SR_NEED_SIG)
|
||||||
{
|
{
|
||||||
gcry_sexp_t s_pkey;
|
gcry_sexp_t s_pkey;
|
||||||
size_t n;
|
|
||||||
unsigned char grip[20];
|
unsigned char grip[20];
|
||||||
char hexgrip[41];
|
char hexgrip[41];
|
||||||
unsigned char *sigval, *newsigval;
|
unsigned char *sigval, *newsigval;
|
||||||
@ -1337,14 +1440,7 @@ create_request (ctrl_t ctrl,
|
|||||||
void *tbsdata;
|
void *tbsdata;
|
||||||
size_t tbsdatalen;
|
size_t tbsdatalen;
|
||||||
|
|
||||||
n = gcry_sexp_canon_len (sigkey, 0, NULL, NULL);
|
rc = gcry_sexp_sscan (&s_pkey, NULL, (const char*)sigkey, sigkeylen);
|
||||||
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);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (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);
|
gcry_sexp_release (s_pkey);
|
||||||
bin2hex (grip, 20, hexgrip);
|
bin2hex (grip, 20, hexgrip);
|
||||||
|
|
||||||
log_info ("about to sign the %s for key: &%s\n",
|
if (!opt.quiet)
|
||||||
certmode? "certificate":"CSR", hexgrip);
|
log_info ("about to sign the %s for key: &%s\n",
|
||||||
|
certmode? "certificate":"CSR", hexgrip);
|
||||||
|
|
||||||
if (carddirect && !certmode)
|
if (carddirect && !certmode)
|
||||||
{
|
{
|
||||||
@ -1422,8 +1519,7 @@ create_request (ctrl_t ctrl,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = transform_sigval (sigval, siglen, mdalgo,
|
err = transform_sigval (sigval, siglen, mdalgo, &newsigval, NULL);
|
||||||
&newsigval, NULL);
|
|
||||||
xfree (sigval);
|
xfree (sigval);
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user