9bd229ac93a4d5ae9a5a1c375b7a565b09ce8c0d
[exim.git] / src / src / pdkim / pdkim-rsa.c
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
11 OpenSSL 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
18 RSAPublicKey ASN1 container
19   0:d=0  hl=3 l= 137 cons: SEQUENCE
20   3:d=1  hl=3 l= 129 prim: INTEGER:Public modulus
21 135:d=1  hl=2 l=   3 prim: INTEGER:Public exponent
22 */
23
24 int 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  */
70 int 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 }