URI:
       tpkcs1.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tpkcs1.c (3693B)
       ---
            1 #include "std.h"
            2 #include "dat.h"
            3 
            4 /*
            5  * PKCS #1 v2.0 signatures (aka RSASSA-PKCS1-V1_5)
            6  *
            7  * You don't want to read the spec.
            8  * Here is what you need to know.
            9  *
           10  * RSA sign (aka RSASP1) is just an RSA encryption.
           11  * RSA verify (aka RSAVP1) is just an RSA decryption.
           12  *
           13  * We sign hashes of messages instead of the messages
           14  * themselves.
           15  *
           16  * The hashes are encoded in ASN.1 DER to identify
           17  * the signature type, and then prefixed with 0x01 PAD 0x00
           18  * where PAD is as many 0xFF bytes as desired.
           19  */
           20 
           21 static int mkasn1(uchar *asn1, DigestAlg *alg, uchar *d, uint dlen);
           22 
           23 int
           24 rsasign(RSApriv *key, DigestAlg *hash, uchar *digest, uint dlen,
           25         uchar *sig, uint siglen)
           26 {
           27         uchar asn1[64], *buf;
           28         int n, len, pad;
           29         mpint *m, *s;
           30 
           31         /*
           32          * Create ASN.1
           33          */
           34         n = mkasn1(asn1, hash, digest, dlen);
           35 
           36         /*
           37          * Create number to sign.
           38          */
           39         len = (mpsignif(key->pub.n)+7)/8 - 1;
           40         if(len < n+2){
           41                 werrstr("rsa key too short");
           42                 return -1;
           43         }
           44         pad = len - (n+2);
           45         if(siglen < len){
           46                 werrstr("signature buffer too short");
           47                 return -1;
           48         }
           49         buf = malloc(len);
           50         if(buf == nil)
           51                 return -1;
           52         buf[0] = 0x01;
           53         memset(buf+1, 0xFF, pad);
           54         buf[1+pad] = 0x00;
           55         memmove(buf+1+pad+1, asn1, n);
           56         m = betomp(buf, len, nil);
           57         free(buf);
           58         if(m == nil)
           59                 return -1;
           60 
           61         /*
           62          * Sign it.
           63          */
           64         s = rsadecrypt(key, m, nil);
           65         mpfree(m);
           66         if(s == nil)
           67                 return -1;
           68         mptoberjust(s, sig, len+1);
           69         mpfree(s);
           70         return len+1;
           71 }
           72 
           73 int
           74 rsaverify(RSApub *key, DigestAlg *hash, uchar *digest, uint dlen,
           75         uchar *sig, uint siglen)
           76 {
           77         uchar asn1[64], xasn1[64];
           78         int n, nn;
           79         mpint *m, *s;
           80 
           81         /*
           82          * Create ASN.1
           83          */
           84         n = mkasn1(asn1, hash, digest, dlen);
           85 
           86         /*
           87          * Extract plaintext of signature.
           88          */
           89         s = betomp(sig, siglen, nil);
           90         if(s == nil)
           91                 return -1;
           92         m = rsaencrypt(key, s, nil);
           93         mpfree(s);
           94         if(m == nil)
           95                 return -1;
           96         nn = mptobe(m, xasn1, sizeof xasn1, nil);
           97         mpfree(m);
           98         if(n != nn || memcmp(asn1, xasn1, n) != 0){
           99                 werrstr("signature did not verify");
          100                 return -1;
          101         }
          102         return 0;
          103 }
          104 
          105 /*
          106  * Mptobe but shift right to fill buffer.
          107  */
          108 void
          109 mptoberjust(mpint *b, uchar *buf, uint len)
          110 {
          111         int n;
          112 
          113         n = mptobe(b, buf, len, nil);
          114         assert(n >= 0);
          115         if(n < len){
          116                 len -= n;
          117                 memmove(buf+len, buf, n);
          118                 memset(buf, 0, len);
          119         }
          120 }
          121 
          122 /*
          123  * Simple ASN.1 encodings.
          124  * Lengths < 128 are encoded as 1-bytes constants,
          125  * making our life easy.
          126  */
          127 
          128 /*
          129  * Hash OIDs
          130  *
          131  * SHA1 = 1.3.14.3.2.26
          132  * MDx = 1.2.840.113549.2.x
          133  */
          134 #define O0(a,b)        ((a)*40+(b))
          135 #define O2(x)        \
          136         (((x)>>7)&0x7F)|0x80, \
          137         ((x)&0x7F)
          138 #define O3(x)        \
          139         (((x)>>14)&0x7F)|0x80, \
          140         (((x)>>7)&0x7F)|0x80, \
          141         ((x)&0x7F)
          142 uchar oidsha1[] = { O0(1, 3), 14, 3, 2, 26 };
          143 uchar oidmd2[] = { O0(1, 2), O2(840), O3(113549), 2, 2 };
          144 uchar oidmd5[] = { O0(1, 2), O2(840), O3(113549), 2, 5 };
          145 
          146 /*
          147  *        DigestInfo ::= SEQUENCE {
          148  *                digestAlgorithm AlgorithmIdentifier,
          149  *                digest OCTET STRING
          150  *        }
          151  *
          152  * except that OpenSSL seems to sign
          153  *
          154  *        DigestInfo ::= SEQUENCE {
          155  *                SEQUENCE{ digestAlgorithm AlgorithmIdentifier, NULL }
          156  *                digest OCTET STRING
          157  *        }
          158  *
          159  * instead.  Sigh.
          160  */
          161 static int
          162 mkasn1(uchar *asn1, DigestAlg *alg, uchar *d, uint dlen)
          163 {
          164         uchar *obj, *p;
          165         uint olen;
          166 
          167         if(alg == sha1){
          168                 obj = oidsha1;
          169                 olen = sizeof(oidsha1);
          170         }else if(alg == md5){
          171                 obj = oidmd5;
          172                 olen = sizeof(oidmd5);
          173         }else{
          174                 sysfatal("bad alg in mkasn1");
          175                 return -1;
          176         }
          177 
          178         p = asn1;
          179         *p++ = 0x30;        /* sequence */
          180         p++;
          181 
          182         *p++ = 0x30;        /* another sequence */
          183         p++;
          184 
          185         *p++ = 0x06;        /* object id */
          186         *p++ = olen;
          187         memmove(p, obj, olen);
          188         p += olen;
          189 
          190         *p++ = 0x05;        /* null */
          191         *p++ = 0;
          192 
          193         asn1[3] = p - (asn1+4);        /* end of inner sequence */
          194 
          195         *p++ = 0x04;        /* octet string */
          196         *p++ = dlen;
          197         memmove(p, d, dlen);
          198         p += dlen;
          199 
          200         asn1[1] = p - (asn1+2);        /* end of outer sequence */
          201         return p-asn1;
          202 }