Consolidate base64 encode/decode routines.
[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             return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
86
87         s1 += 31;
88         if( *s1 == '\r' ) s1++;
89         if( *s1 == '\n' ) s1++;
90             else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
91
92         enc = 0;
93
94         if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
95         {
96             return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
97         }
98
99         len = 0;
100         {
101         extern unsigned char * string_copyn(const unsigned char *, int);
102         extern int b64decode(unsigned char *, unsigned char **);
103 #define POLARSSL_ERR_BASE64_INVALID_CHARACTER              0x0012
104
105         s1 = string_copyn(s1, s2-s1); /* need nul-terminated string */
106         if ((len = b64decode(s1, &buf)) < 0)
107             return POLARSSL_ERR_BASE64_INVALID_CHARACTER
108                 | POLARSSL_ERR_X509_KEY_INVALID_PEM;
109         }
110
111         buflen = len;
112
113         if( enc != 0 )
114         {
115             return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
116         }
117     }
118
119     memset( rsa, 0, sizeof( rsa_context ) );
120
121     p = buf;
122     end = buf + buflen;
123
124     /*
125      *  RSAPrivateKey ::= SEQUENCE {
126      *      version           Version,
127      *      modulus           INTEGER,  -- n
128      *      publicExponent    INTEGER,  -- e
129      *      privateExponent   INTEGER,  -- d
130      *      prime1            INTEGER,  -- p
131      *      prime2            INTEGER,  -- q
132      *      exponent1         INTEGER,  -- d mod (p-1)
133      *      exponent2         INTEGER,  -- d mod (q-1)
134      *      coefficient       INTEGER,  -- (inverse of q) mod p
135      *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
136      *  }
137      */
138     if( ( ret = asn1_get_tag( &p, end, &len,
139             ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
140     {
141         rsa_free( rsa );
142         return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
143     }
144
145     end = p + len;
146
147     if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
148     {
149         rsa_free( rsa );
150         return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
151     }
152
153     if( rsa->ver != 0 )
154     {
155         rsa_free( rsa );
156         return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
157     }
158
159     if( ( ret = asn1_get_mpi( &p, end, &rsa->N  ) ) != 0 ||
160         ( ret = asn1_get_mpi( &p, end, &rsa->E  ) ) != 0 ||
161         ( ret = asn1_get_mpi( &p, end, &rsa->D  ) ) != 0 ||
162         ( ret = asn1_get_mpi( &p, end, &rsa->P  ) ) != 0 ||
163         ( ret = asn1_get_mpi( &p, end, &rsa->Q  ) ) != 0 ||
164         ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
165         ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
166         ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
167     {
168         rsa_free( rsa );
169         return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
170     }
171
172     rsa->len = mpi_size( &rsa->N );
173
174     if( p != end )
175     {
176         rsa_free( rsa );
177         return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
178                 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
179     }
180
181     if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
182     {
183         rsa_free( rsa );
184         return( ret );
185     }
186
187     return( 0 );
188 }