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