7f98fb008037581a69fcf31041d3c235dc36dd62
[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 }