#include <mp.h>
#include <libsec.h>
-typedef DigestState*(*DigestFun)(uchar*,ulong,uchar*,DigestState*);
-
/* ANSI offsetof, backwards. */
#define OFFSETOF(a, b) offsetof(b, a)
static char*
estrdup(char *s)
{
- char *d, *d0;
+ char *d;
+ int n;
- if(!s)
- return 0;
- d = d0 = emalloc(strlen(s)+1);
- while(*d++ = *s++)
- ;
- return d0;
+ n = strlen(s)+1;
+ d = emalloc(n);
+ memmove(d, s, n);
+ return d;
}
{
Bytes* ans;
+ if(len < 0)
+ abort();
ans = (Bytes*)emalloc(OFFSETOF(data[0], Bytes) + len);
ans->len = len;
return ans;
static void
freebytes(Bytes* b)
{
- if(b != nil)
- free(b);
+ free(b);
}
/*
{
Ints* ans;
+ if(len < 0 || len > ((uint)-1>>1)/sizeof(int))
+ abort();
ans = (Ints*)emalloc(OFFSETOF(data[0], Ints) + len*sizeof(int));
ans->len = len;
return ans;
Ints* ans;
ans = newints(len);
- if(len > 0)
- memmove(ans->data, buf, len*sizeof(int));
+ memmove(ans->data, buf, len*sizeof(int));
return ans;
}
static void
freeints(Ints* b)
{
- if(b != nil)
- free(b);
+ free(b);
}
/* len is number of bytes */
{
Bits* ans;
+ if(len < 0)
+ abort();
ans = (Bits*)emalloc(OFFSETOF(data[0], Bits) + len);
ans->len = len;
ans->unusedbits = 0;
static void
freebits(Bits* b)
{
- if(b != nil)
- free(b);
+ free(b);
}
static Elist*
el = v->u.seqval;
for(l = el; l != nil; l = l->tl)
freevalfields(&l->hd.val);
- if(el)
- freeelist(el);
+ freeelist(el);
break;
case VSet:
el = v->u.setval;
for(l = el; l != nil; l = l->tl)
freevalfields(&l->hd.val);
- if(el)
- freeelist(el);
+ freeelist(el);
break;
}
}
ALG_md2WithRSAEncryption,
ALG_md4WithRSAEncryption,
ALG_md5WithRSAEncryption,
+
ALG_sha1WithRSAEncryption,
ALG_sha1WithRSAEncryptionOiw,
+
ALG_sha256WithRSAEncryption,
+ ALG_sha384WithRSAEncryption,
+ ALG_sha512WithRSAEncryption,
+ ALG_sha224WithRSAEncryption,
+
ALG_md5,
+ ALG_sha1,
+ ALG_sha256,
+ ALG_sha384,
+ ALG_sha512,
+ ALG_sha224,
+
NUMALGS
};
-typedef struct Ints7 {
+
+typedef struct Ints15 {
int len;
- int data[7];
-} Ints7;
-static Ints7 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 };
-static Ints7 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 };
-static Ints7 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };
-static Ints7 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 };
-static Ints7 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 };
-static Ints7 oid_sha1WithRSAEncryptionOiw ={6, 1, 3, 14, 3, 2, 29 };
-static Ints7 oid_sha256WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 11 };
-static Ints7 oid_md5 ={6, 1, 2, 840, 113549, 2, 5, 0 };
+ int data[15];
+} Ints15;
+
+typedef struct DigestAlg {
+ int alg;
+ DigestState* (*fun)(uchar*,ulong,uchar*,DigestState*);
+ int len;
+} DigestAlg;
+
+static DigestAlg alg_md5 = { ALG_md5, md5, MD5dlen};
+static DigestAlg alg_sha1 = { ALG_sha1, sha1, SHA1dlen };
+static DigestAlg alg_sha256 = { ALG_sha256, sha2_256, SHA2_256dlen };
+static DigestAlg alg_sha384 = { ALG_sha384, sha2_384, SHA2_384dlen };
+static DigestAlg alg_sha512 = { ALG_sha512, sha2_512, SHA2_512dlen };
+static DigestAlg alg_sha224 = { ALG_sha224, sha2_224, SHA2_224dlen };
+
+/* maximum length of digest output of the digest algs above */
+enum {
+ MAXdlen = SHA2_512dlen,
+};
+
+static Ints15 oid_rsaEncryption = {7, 1, 2, 840, 113549, 1, 1, 1 };
+static Ints15 oid_md2WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 2 };
+static Ints15 oid_md4WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 3 };
+static Ints15 oid_md5WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 4 };
+static Ints15 oid_sha1WithRSAEncryption ={7, 1, 2, 840, 113549, 1, 1, 5 };
+static Ints15 oid_sha1WithRSAEncryptionOiw ={6, 1, 3, 14, 3, 2, 29 };
+static Ints15 oid_sha256WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 11 };
+static Ints15 oid_sha384WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 12 };
+static Ints15 oid_sha512WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 13 };
+static Ints15 oid_sha224WithRSAEncryption = {7, 1, 2, 840, 113549, 1, 1, 14 };
+
+static Ints15 oid_md5 = {6, 1, 2, 840, 113549, 2, 5 };
+static Ints15 oid_sha1 = {6, 1, 3, 14, 3, 2, 26 };
+static Ints15 oid_sha256= {9, 2, 16, 840, 1, 101, 3, 4, 2, 1 };
+static Ints15 oid_sha384= {9, 2, 16, 840, 1, 101, 3, 4, 2, 2 };
+static Ints15 oid_sha512= {9, 2, 16, 840, 1, 101, 3, 4, 2, 3 };
+static Ints15 oid_sha224= {9, 2, 16, 840, 1, 101, 3, 4, 2, 4 };
+
static Ints *alg_oid_tab[NUMALGS+1] = {
(Ints*)&oid_rsaEncryption,
(Ints*)&oid_md2WithRSAEncryption,
(Ints*)&oid_md4WithRSAEncryption,
(Ints*)&oid_md5WithRSAEncryption,
+
(Ints*)&oid_sha1WithRSAEncryption,
(Ints*)&oid_sha1WithRSAEncryptionOiw,
+
(Ints*)&oid_sha256WithRSAEncryption,
+ (Ints*)&oid_sha384WithRSAEncryption,
+ (Ints*)&oid_sha512WithRSAEncryption,
+ (Ints*)&oid_sha224WithRSAEncryption,
+
(Ints*)&oid_md5,
+ (Ints*)&oid_sha1,
+ (Ints*)&oid_sha256,
+ (Ints*)&oid_sha384,
+ (Ints*)&oid_sha512,
+ (Ints*)&oid_sha224,
nil
};
-static DigestFun digestalg[NUMALGS+1] = {
- md5, md5, md5, md5, sha1, sha1, sha2_256, md5, nil
+
+static DigestAlg *digestalg[NUMALGS+1] = {
+ &alg_md5, &alg_md5, &alg_md5, &alg_md5,
+ &alg_sha1, &alg_sha1,
+ &alg_sha256, &alg_sha384, &alg_sha512, &alg_sha224,
+ &alg_md5, &alg_sha1, &alg_sha256, &alg_sha384, &alg_sha512, &alg_sha224,
+ nil
};
static void
freecert(CertX509* c)
{
- if(!c) return;
- if(c->issuer != nil)
- free(c->issuer);
- if(c->validity_start != nil)
- free(c->validity_start);
- if(c->validity_end != nil)
- free(c->validity_end);
- if(c->subject != nil)
- free(c->subject);
+ if(c == nil)
+ return;
+ free(c->issuer);
+ free(c->validity_start);
+ free(c->validity_end);
+ free(c->subject);
freebytes(c->publickey);
freebytes(c->signature);
free(c);
if(mp == nil)
goto errret;
- if(l != nil)
- freeelist(l);
+ freeelist(l);
return key;
errret:
- if(l != nil)
- freeelist(l);
+ freeelist(l);
rsapubfree(key);
return nil;
}
* Our ASN.1 library doesn't return pointers into the original
* data array, so we need to do a little hand decoding.
*/
-static void
-digest_certinfo(Bytes *cert, DigestFun digestfun, uchar *digest)
+static int
+digest_certinfo(Bytes *cert, DigestAlg *da, uchar *digest)
{
uchar *info, *p, *pend;
ulong infolen;
length_decode(&p, pend, &length) != ASN_OK ||
p+length > pend ||
p+length < p)
- return;
+ return -1;
info = p;
if(ber_decode(&p, pend, &elem) != ASN_OK)
- return;
+ return -1;
freevalfields(&elem.val);
if(elem.tag.num != SEQUENCE)
- return;
+ return -1;
infolen = p - info;
- (*digestfun)(info, infolen, digest, nil);
+ (*da->fun)(info, infolen, digest, nil);
+ return da->len;
}
static char*
-verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, Elem **psigalg)
+verify_signature(Bytes* signature, RSApub *pk, uchar *edigest, int edigestlen, Elem **psigalg)
{
Elem e;
Elist *el;
err = "expected 1";
goto end;
}
- buf++;
- while(buf[0] == 0xff)
- buf++;
- if(buf[0] != 0) {
+ buf++, buflen--;
+ while(buflen > 0 && buf[0] == 0xff)
+ buf++, buflen--;
+ if(buflen < 1 || buf[0] != 0) {
err = "expected 0";
goto end;
}
- buf++;
- buflen -= buf-pkcs1buf;
+ buf++, buflen--;
if(decode(buf, buflen, &e) != ASN_OK || !is_seq(&e, &el) || elistlen(el) != 2 ||
!is_octetstring(&el->tl->hd, &digest)) {
err = "signature parse error";
goto end;
}
*psigalg = &el->hd;
- if(memcmp(digest->data, edigest, digest->len) == 0)
+ if(digest->len != edigestlen) {
+ err = "bad digest length";
goto end;
- err = "digests did not match";
+ }
+ if(constcmp(digest->data, edigest, edigestlen) != 0)
+ err = "digests did not match";
end:
- if(pkcs1 != nil)
- mpfree(pkcs1);
- if(pkcs1buf != nil)
- free(pkcs1buf);
+ mpfree(pkcs1);
+ free(pkcs1buf);
return err;
}
char *e;
Bytes *b;
CertX509 *c;
- uchar digest[SHA1dlen];
+ int digestlen;
+ uchar digest[MAXdlen];
Elem *sigalg;
b = makebytes(cert, ncert);
c = decode_cert(b);
- if(c != nil)
- digest_certinfo(b, digestalg[c->signature_alg], digest);
- freebytes(b);
- if(c == nil)
+ if(c == nil){
+ freebytes(b);
return "cannot decode cert";
- e = verify_signature(c->signature, pk, digest, &sigalg);
+ }
+ digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
+ freebytes(b);
+ if(digestlen <= 0){
+ freecert(c);
+ return "cannot decode certinfo";
+ }
+ e = verify_signature(c->signature, pk, digest, digestlen, &sigalg);
freecert(c);
return e;
}
e.tag.class = Universal;
e.tag.num = UTCTime;
e.val.tag = VString;
- snprint(utc, 50, "%.2d%.2d%.2d%.2d%.2d%.2dZ",
+ snprint(utc, sizeof(utc), "%.2d%.2d%.2d%.2d%.2d%.2dZ",
tm->year % 100, tm->mon+1, tm->mday, tm->hour, tm->min, tm->sec);
e.val.u.stringval = estrdup(utc);
return e;
uchar*
X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen)
{
- int serial = 0;
+ int serial = 0, sigalg = ALG_sha256WithRSAEncryption;
uchar *cert = nil;
RSApub *pk = rsaprivtopub(priv);
Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;
Elem e, certinfo, issuer, subject, pubkey, validity, sig;
- uchar digest[MD5dlen], *buf;
+ DigestAlg *da;
+ uchar digest[MAXdlen], *buf;
int buflen;
mpint *pkcs1;
nil)));
certinfo = mkseq(
mkel(mkint(serial),
- mkel(mkalg(ALG_md5WithRSAEncryption),
+ mkel(mkalg(sigalg),
mkel(issuer,
mkel(validity,
mkel(subject,
nil)))))));
if(encode(certinfo, &certinfobytes) != ASN_OK)
goto errret;
- md5(certinfobytes->data, certinfobytes->len, digest, 0);
+ da = digestalg[sigalg];
+ (*da->fun)(certinfobytes->data, certinfobytes->len, digest, 0);
freebytes(certinfobytes);
sig = mkseq(
- mkel(mkalg(ALG_md5),
- mkel(mkoctet(digest, MD5dlen),
+ mkel(mkalg(da->alg),
+ mkel(mkoctet(digest, da->len),
nil)));
if(encode(sig, &sigbytes) != ASN_OK)
goto errret;
mpfree(pkcs1);
e = mkseq(
mkel(certinfo,
- mkel(mkalg(ALG_md5WithRSAEncryption),
+ mkel(mkalg(sigalg),
mkel(mkbits(buf, buflen),
nil))));
free(buf);
X509req(RSApriv *priv, char *subj, int *certlen)
{
/* RFC 2314, PKCS #10 Certification Request Syntax */
- int version = 0;
+ int version = 0, sigalg = ALG_sha256WithRSAEncryption;
uchar *cert = nil;
RSApub *pk = rsaprivtopub(priv);
Bytes *certbytes, *pkbytes, *certinfobytes, *sigbytes;
Elem e, certinfo, subject, pubkey, sig;
- uchar digest[MD5dlen], *buf;
+ DigestAlg *da;
+ uchar digest[MAXdlen], *buf;
int buflen;
mpint *pkcs1;
nil))));
if(encode(certinfo, &certinfobytes) != ASN_OK)
goto errret;
- md5(certinfobytes->data, certinfobytes->len, digest, 0);
+ da = digestalg[sigalg];
+ (*da->fun)(certinfobytes->data, certinfobytes->len, digest, 0);
freebytes(certinfobytes);
sig = mkseq(
- mkel(mkalg(ALG_md5),
- mkel(mkoctet(digest, MD5dlen),
+ mkel(mkalg(da->alg),
+ mkel(mkoctet(digest, da->len),
nil)));
if(encode(sig, &sigbytes) != ASN_OK)
goto errret;
mpfree(pkcs1);
e = mkseq(
mkel(certinfo,
- mkel(mkalg(ALG_md5),
+ mkel(mkalg(sigalg),
mkel(mkbits(buf, buflen),
nil))));
free(buf);
Bytes *b;
CertX509 *c;
RSApub *pk;
- uchar digest[SHA1dlen];
+ int digestlen;
+ uchar digest[MAXdlen];
Elem *sigalg;
print("begin X509dump\n");
b = makebytes(cert, ncert);
c = decode_cert(b);
- if(c != nil)
- digest_certinfo(b, digestalg[c->signature_alg], digest);
- freebytes(b);
if(c == nil){
- print("cannot decode cert");
+ freebytes(b);
+ print("cannot decode cert\n");
+ return;
+ }
+ digestlen = digest_certinfo(b, digestalg[c->signature_alg], digest);
+ freebytes(b);
+ if(digestlen <= 0){
+ freecert(c);
+ print("cannot decode certinfo\n");
return;
}
pk = decode_rsapubkey(c->publickey);
print("pubkey e=%B n(%d)=%B\n", pk->ek, mpsignif(pk->n), pk->n);
- print("sigalg=%d digest=%.*H\n", c->signature_alg, MD5dlen, digest);
- e = verify_signature(c->signature, pk, digest, &sigalg);
+ print("sigalg=%d digest=%.*H\n", c->signature_alg, digestlen, digest);
+ e = verify_signature(c->signature, pk, digest, digestlen, &sigalg);
if(e==nil){
e = "nil (meaning ok)";
print("sigalg=\n");