fix no-ssl build
[exim.git] / src / src / pdkim / pdkim-rsa.c
1 #include "pdkim-rsa.h"
2 #include <stdlib.h>
3 #include <string.h>
4 #include "polarssl/private-x509parse_c.h"
5
6 /* PDKIM code (not copied from polarssl) */
7 /*
8 * Parse a public RSA key
9
10 OpenSSL RSA public key ASN1 container
11 0:d=0 hl=3 l= 159 cons: SEQUENCE
12 3:d=1 hl=2 l= 13 cons: SEQUENCE
13 5:d=2 hl=2 l= 9 prim: OBJECT:rsaEncryption
14 16:d=2 hl=2 l= 0 prim: NULL
15 18:d=1 hl=3 l= 141 prim: BIT STRING:RSAPublicKey (below)
16
17 RSAPublicKey ASN1 container
18 0:d=0 hl=3 l= 137 cons: SEQUENCE
19 3:d=1 hl=3 l= 129 prim: INTEGER:Public modulus
20 135:d=1 hl=2 l= 3 prim: INTEGER:Public exponent
21 */
22
23 int rsa_parse_public_key( rsa_context *rsa, unsigned char *buf, int buflen )
24 {
25 unsigned char *p, *end;
26 int ret, len;
27
28 p = buf;
29 end = buf+buflen;
30
31 if( ( ret = asn1_get_tag( &p, end, &len,
32 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) {
33 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
34 }
35
36 if( ( ret = asn1_get_tag( &p, end, &len,
37 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) == 0 ) {
38 /* Skip over embedded rsaEncryption Object */
39 p+=len;
40
41 /* The RSAPublicKey ASN1 container is wrapped in a BIT STRING */
42 if( ( ret = asn1_get_tag( &p, end, &len,
43 ASN1_BIT_STRING ) ) != 0 ) {
44 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
45 }
46
47 /* Limit range to that BIT STRING */
48 end = p + len;
49 p++;
50
51 if( ( ret = asn1_get_tag( &p, end, &len,
52 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) {
53 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
54 }
55 }
56
57 if ( ( ( ret = asn1_get_mpi( &p, end, &(rsa->N) ) ) == 0 ) &&
58 ( ( ret = asn1_get_mpi( &p, end, &(rsa->E) ) ) == 0 ) ) {
59 rsa->len = mpi_size( &rsa->N );
60 return 0;
61 }
62
63 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
64 }
65
66 /*
67 * Parse a private RSA key
68 */
69 int rsa_parse_key( rsa_context *rsa, unsigned char *buf, int buflen,
70 unsigned char *pwd, int pwdlen )
71 {
72 int ret, len, enc;
73 unsigned char *s1, *s2;
74 unsigned char *p, *end;
75
76 s1 = (unsigned char *) strstr( (char *) buf,
77 "-----BEGIN RSA PRIVATE KEY-----" );
78
79 if( s1 != NULL )
80 {
81 s2 = (unsigned char *) strstr( (char *) buf,
82 "-----END RSA PRIVATE KEY-----" );
83
84 if( s2 == NULL || s2 <= s1 )
85 {
86 debug_printf("rsa_parse_key: err 1\n");
87 return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
88 }
89
90 s1 += 31;
91 if( *s1 == '\r' ) s1++;
92 if( *s1 == '\n' ) s1++;
93 else
94 {
95 debug_printf("rsa_parse_key: err 2\n");
96 return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
97 }
98
99 enc = 0;
100
101 if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
102 {
103 debug_printf("rsa_parse_key: err 3\n");
104 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
105 }
106
107 len = 0;
108 {
109 extern unsigned char * string_copyn(const unsigned char *, int);
110 extern int b64decode(unsigned char *, unsigned char **);
111 #define POLARSSL_ERR_BASE64_INVALID_CHARACTER 0x0012
112
113 s1 = string_copyn(s1, s2-s1); /* need nul-terminated string */
114 if ((len = b64decode(s1, &buf)) < 0)
115 {
116 debug_printf("rsa_parse_key: err 4\n");
117 return POLARSSL_ERR_BASE64_INVALID_CHARACTER
118 | POLARSSL_ERR_X509_KEY_INVALID_PEM;
119 }
120 }
121
122 buflen = len;
123
124 if( enc != 0 )
125 {
126 debug_printf("rsa_parse_key: err 5\n");
127 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
128 }
129 }
130
131 memset( rsa, 0, sizeof( rsa_context ) );
132
133 p = buf;
134 end = buf + buflen;
135
136 /*
137 * RSAPrivateKey ::= SEQUENCE {
138 * version Version,
139 * modulus INTEGER, -- n
140 * publicExponent INTEGER, -- e
141 * privateExponent INTEGER, -- d
142 * prime1 INTEGER, -- p
143 * prime2 INTEGER, -- q
144 * exponent1 INTEGER, -- d mod (p-1)
145 * exponent2 INTEGER, -- d mod (q-1)
146 * coefficient INTEGER, -- (inverse of q) mod p
147 * otherPrimeInfos OtherPrimeInfos OPTIONAL
148 * }
149 */
150 if( ( ret = asn1_get_tag( &p, end, &len,
151 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
152 {
153 rsa_free( rsa );
154 debug_printf("rsa_parse_key: err 6\n");
155 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
156 }
157
158 end = p + len;
159
160 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
161 {
162 rsa_free( rsa );
163 debug_printf("rsa_parse_key: err 7\n");
164 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
165 }
166
167 if( rsa->ver != 0 )
168 {
169 rsa_free( rsa );
170 debug_printf("rsa_parse_key: err 8\n");
171 return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
172 }
173
174 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
175 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
176 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
177 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
178 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
179 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
180 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
181 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
182 {
183 rsa_free( rsa );
184 debug_printf("rsa_parse_key: err 9\n");
185 return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
186 }
187
188 rsa->len = mpi_size( &rsa->N );
189
190 if( p != end )
191 {
192 rsa_free( rsa );
193 debug_printf("rsa_parse_key: err 10\n");
194 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
195 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
196 }
197
198 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
199 {
200 rsa_free( rsa );
201 debug_printf("rsa_parse_key: err 11\n");
202 return( ret );
203 }
204
205 return( 0 );
206 }