On Sun, Jun 16, 2019 at 08:44:46PM +0200, Theo Buehler wrote:
> On Sun, Jun 16, 2019 at 09:25:45AM +0200, Florian Obser wrote:
> > On Sat, Jun 15, 2019 at 06:20:49PM +0200, Florian Obser wrote:
> > > OK?
> >
> > update to apply cleanly on -current
>
> The acctproc.c change looks ok with some minor comments inline.
> I haven't tried to verify the JSON stuff.
that's fine, Benno reviewed that and ignored the crypto stuff :D
I commited it with the get0 change.
Questions inline
[...]
> > @@ -190,14 +267,19 @@ op_sign_rsa(char **prot, EVP_PKEY *pkey, const char
> > *nonce, const char *url)
> > static int
> > op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
> > {
> > - char *nonce = NULL, *pay = NULL, *pay64 = NULL;
> > - char *prot = NULL, *prot64 = NULL;
> > - char *sign = NULL, *dig64 = NULL, *fin = NULL;
> > - char *url = NULL, *kid = NULL;
> > - unsigned char *dig = NULL;
> > - EVP_MD_CTX *ctx = NULL;
> > - int cc, rc = 0;
> > - unsigned int digsz;
> > + EVP_MD_CTX *ctx = NULL;
> > + const EVP_MD *evp_md = NULL;
> > + EC_KEY *ec;
> > + ECDSA_SIG *ec_sig = NULL;
> > + const BIGNUM *ec_sig_r = NULL, *ec_sig_s = NULL;
> > + int cc, rc = 0;
> > + unsigned int digsz, bufsz, degree, bn_len, r_len, s_len;
> > + char *nonce = NULL, *pay = NULL, *pay64 = NULL;
> > + char *prot = NULL, *prot64 = NULL;
> > + char *sign = NULL, *dig64 = NULL, *fin = NULL;
> > + char *url = NULL, *kid = NULL, *alg = NULL;
> > + unsigned char *dig = NULL, *buf = NULL;
>
> To simplify slightly, you could use
>
> unsigned char dig[EVP_MAX_MD_SIZE];
>
> instead of allocating dig dynamically (EVP_MAX_MD_SIZE is 64).
this doesn't seem to be correct.
} else if (!EVP_SignFinal(ctx, dig, &digsz, pkey)) {
this stores 104 bytes with an NID_secp384r1 key
EVP_MAX_MD_SIZE seems to be about digests, not signatures. Did you
have a different constant in mind or did you get confused by the
poorly worded variable?
[...]
> > + degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec));
> > + bn_len = (degree + 7) / 8;
>
> This calculation is fine if you use curves over a prime field GFp (as
> you currently do), but it will be incorrect if you should ever want to
> use a curve over a binary field GF2m.
I know some of these words!
So this whole song-and-dance is needed because we need to store r and
s with leading zeros, so we need to find out what the maximum
representation length of r and s could be:
/* put r and s in with leading zeros if any */
BN_bn2bin(ec_sig_r, buf + bn_len - r_len);
BN_bn2bin(ec_sig_s, buf + bufsz - s_len);
This is "documented" in RFC7518 Section 3.4.
https://tools.ietf.org/html/rfc7518#section-3.4
But it's kinda documented by example, i.e. it talks about P-256 and
there r and s representations are 32 bytes long. But for P-384 it's 48
bytes. Of course I'm making this all up as I go along.
What would be the correct calculation for a GF2m field? Should I maybe just
ignore it? RFC 7518 only lists P-256, P-384 and P-521 (and I think
Let's Encrypt only supports P-384 anyway), and they are all GFp, no?
Maybe it would be best to skip the whole degree calculation and
hardcode bn_len as 48.
Thanks for your help!
--
I'm not entirely sure you are real.