Blob


1 #include "std.h"
2 #include "dat.h"
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 */
21 static int mkasn1(uchar *asn1, DigestAlg *alg, uchar *d, uint dlen);
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;
31 /*
32 * Create ASN.1
33 */
34 n = mkasn1(asn1, hash, digest, dlen);
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;
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 }
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;
81 /*
82 * Create ASN.1
83 */
84 n = mkasn1(asn1, hash, digest, dlen);
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;
102 return 0;
105 /*
106 * Mptobe but shift right to fill buffer.
107 */
108 void
109 mptoberjust(mpint *b, uchar *buf, uint len)
111 int n;
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);
122 /*
123 * Simple ASN.1 encodings.
124 * Lengths < 128 are encoded as 1-bytes constants,
125 * making our life easy.
126 */
128 /*
129 * Hash OIDs
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 };
146 /*
147 * DigestInfo ::= SEQUENCE {
148 * digestAlgorithm AlgorithmIdentifier,
149 * digest OCTET STRING
150 * }
152 * except that OpenSSL seems to sign
154 * DigestInfo ::= SEQUENCE {
155 * SEQUENCE{ digestAlgorithm AlgorithmIdentifier, NULL }
156 * digest OCTET STRING
157 * }
159 * instead. Sigh.
160 */
161 static int
162 mkasn1(uchar *asn1, DigestAlg *alg, uchar *d, uint dlen)
164 uchar *obj, *p;
165 uint olen;
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;
178 p = asn1;
179 *p++ = 0x30; /* sequence */
180 p++;
182 *p++ = 0x30; /* another sequence */
183 p++;
185 *p++ = 0x06; /* object id */
186 *p++ = olen;
187 memmove(p, obj, olen);
188 p += olen;
190 *p++ = 0x05; /* null */
191 *p++ = 0;
193 asn1[3] = p - (asn1+4); /* end of inner sequence */
195 *p++ = 0x04; /* octet string */
196 *p++ = dlen;
197 memmove(p, d, dlen);
198 p += dlen;
200 asn1[1] = p - (asn1+2); /* end of outer sequence */
201 return p-asn1;