PolarSSL v1.3.9
pem.c
Go to the documentation of this file.
1 /*
2  * Privacy Enhanced Mail (PEM) decoding
3  *
4  * Copyright (C) 2006-2014, Brainspark B.V.
5  *
6  * This file is part of PolarSSL (http://www.polarssl.org)
7  * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8  *
9  * All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 
26 #if !defined(POLARSSL_CONFIG_FILE)
27 #include "polarssl/config.h"
28 #else
29 #include POLARSSL_CONFIG_FILE
30 #endif
31 
32 #if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C)
33 #include "polarssl/pem.h"
34 #include "polarssl/base64.h"
35 #include "polarssl/des.h"
36 #include "polarssl/aes.h"
37 #include "polarssl/md5.h"
38 #include "polarssl/cipher.h"
39 
40 #if defined(POLARSSL_PLATFORM_C)
41 #include "polarssl/platform.h"
42 #else
43 #define polarssl_malloc malloc
44 #define polarssl_free free
45 #endif
46 
47 #include <stdlib.h>
48 
49 /* Implementation that should never be optimized out by the compiler */
50 static void polarssl_zeroize( void *v, size_t n ) {
51  volatile unsigned char *p = v; while( n-- ) *p++ = 0;
52 }
53 
54 #if defined(POLARSSL_PEM_PARSE_C)
55 void pem_init( pem_context *ctx )
56 {
57  memset( ctx, 0, sizeof( pem_context ) );
58 }
59 
60 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \
61  ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
62 /*
63  * Read a 16-byte hex string and convert it to binary
64  */
65 static int pem_get_iv( const unsigned char *s, unsigned char *iv,
66  size_t iv_len )
67 {
68  size_t i, j, k;
69 
70  memset( iv, 0, iv_len );
71 
72  for( i = 0; i < iv_len * 2; i++, s++ )
73  {
74  if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
75  if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
76  if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
78 
79  k = ( ( i & 1 ) != 0 ) ? j : j << 4;
80 
81  iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
82  }
83 
84  return( 0 );
85 }
86 
87 static void pem_pbkdf1( unsigned char *key, size_t keylen,
88  unsigned char *iv,
89  const unsigned char *pwd, size_t pwdlen )
90 {
91  md5_context md5_ctx;
92  unsigned char md5sum[16];
93  size_t use_len;
94 
95  md5_init( &md5_ctx );
96 
97  /*
98  * key[ 0..15] = MD5(pwd || IV)
99  */
100  md5_starts( &md5_ctx );
101  md5_update( &md5_ctx, pwd, pwdlen );
102  md5_update( &md5_ctx, iv, 8 );
103  md5_finish( &md5_ctx, md5sum );
104 
105  if( keylen <= 16 )
106  {
107  memcpy( key, md5sum, keylen );
108 
109  md5_free( &md5_ctx );
110  polarssl_zeroize( md5sum, 16 );
111  return;
112  }
113 
114  memcpy( key, md5sum, 16 );
115 
116  /*
117  * key[16..23] = MD5(key[ 0..15] || pwd || IV])
118  */
119  md5_starts( &md5_ctx );
120  md5_update( &md5_ctx, md5sum, 16 );
121  md5_update( &md5_ctx, pwd, pwdlen );
122  md5_update( &md5_ctx, iv, 8 );
123  md5_finish( &md5_ctx, md5sum );
124 
125  use_len = 16;
126  if( keylen < 32 )
127  use_len = keylen - 16;
128 
129  memcpy( key + 16, md5sum, use_len );
130 
131  md5_free( &md5_ctx );
132  polarssl_zeroize( md5sum, 16 );
133 }
134 
135 #if defined(POLARSSL_DES_C)
136 /*
137  * Decrypt with DES-CBC, using PBKDF1 for key derivation
138  */
139 static void pem_des_decrypt( unsigned char des_iv[8],
140  unsigned char *buf, size_t buflen,
141  const unsigned char *pwd, size_t pwdlen )
142 {
143  des_context des_ctx;
144  unsigned char des_key[8];
145 
146  des_init( &des_ctx );
147 
148  pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
149 
150  des_setkey_dec( &des_ctx, des_key );
151  des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen,
152  des_iv, buf, buf );
153 
154  des_free( &des_ctx );
155  polarssl_zeroize( des_key, 8 );
156 }
157 
158 /*
159  * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
160  */
161 static void pem_des3_decrypt( unsigned char des3_iv[8],
162  unsigned char *buf, size_t buflen,
163  const unsigned char *pwd, size_t pwdlen )
164 {
165  des3_context des3_ctx;
166  unsigned char des3_key[24];
167 
168  des3_init( &des3_ctx );
169 
170  pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
171 
172  des3_set3key_dec( &des3_ctx, des3_key );
173  des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
174  des3_iv, buf, buf );
175 
176  des3_free( &des3_ctx );
177  polarssl_zeroize( des3_key, 24 );
178 }
179 #endif /* POLARSSL_DES_C */
180 
181 #if defined(POLARSSL_AES_C)
182 /*
183  * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
184  */
185 static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
186  unsigned char *buf, size_t buflen,
187  const unsigned char *pwd, size_t pwdlen )
188 {
189  aes_context aes_ctx;
190  unsigned char aes_key[32];
191 
192  aes_init( &aes_ctx );
193 
194  pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
195 
196  aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 );
197  aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen,
198  aes_iv, buf, buf );
199 
200  aes_free( &aes_ctx );
201  polarssl_zeroize( aes_key, keylen );
202 }
203 #endif /* POLARSSL_AES_C */
204 
205 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
206  ( POLARSSL_AES_C || POLARSSL_DES_C ) */
207 
208 int pem_read_buffer( pem_context *ctx, const char *header, const char *footer,
209  const unsigned char *data, const unsigned char *pwd,
210  size_t pwdlen, size_t *use_len )
211 {
212  int ret, enc;
213  size_t len;
214  unsigned char *buf;
215  const unsigned char *s1, *s2, *end;
216 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \
217  ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
218  unsigned char pem_iv[16];
220 #else
221  ((void) pwd);
222  ((void) pwdlen);
223 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
224  ( POLARSSL_AES_C || POLARSSL_DES_C ) */
225 
226  if( ctx == NULL )
228 
229  s1 = (unsigned char *) strstr( (const char *) data, header );
230 
231  if( s1 == NULL )
233 
234  s2 = (unsigned char *) strstr( (const char *) data, footer );
235 
236  if( s2 == NULL || s2 <= s1 )
238 
239  s1 += strlen( header );
240  if( *s1 == '\r' ) s1++;
241  if( *s1 == '\n' ) s1++;
243 
244  end = s2;
245  end += strlen( footer );
246  if( *end == '\r' ) end++;
247  if( *end == '\n' ) end++;
248  *use_len = end - data;
249 
250  enc = 0;
251 
252  if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
253  {
254 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \
255  ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
256  enc++;
257 
258  s1 += 22;
259  if( *s1 == '\r' ) s1++;
260  if( *s1 == '\n' ) s1++;
261  else return( POLARSSL_ERR_PEM_INVALID_DATA );
262 
263 
264 #if defined(POLARSSL_DES_C)
265  if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
266  {
268 
269  s1 += 23;
270  if( pem_get_iv( s1, pem_iv, 8 ) != 0 )
272 
273  s1 += 16;
274  }
275  else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
276  {
277  enc_alg = POLARSSL_CIPHER_DES_CBC;
278 
279  s1 += 18;
280  if( pem_get_iv( s1, pem_iv, 8) != 0 )
282 
283  s1 += 16;
284  }
285 #endif /* POLARSSL_DES_C */
286 
287 #if defined(POLARSSL_AES_C)
288  if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
289  {
290  if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
291  enc_alg = POLARSSL_CIPHER_AES_128_CBC;
292  else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
293  enc_alg = POLARSSL_CIPHER_AES_192_CBC;
294  else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
295  enc_alg = POLARSSL_CIPHER_AES_256_CBC;
296  else
298 
299  s1 += 22;
300  if( pem_get_iv( s1, pem_iv, 16 ) != 0 )
302 
303  s1 += 32;
304  }
305 #endif /* POLARSSL_AES_C */
306 
307  if( enc_alg == POLARSSL_CIPHER_NONE )
309 
310  if( *s1 == '\r' ) s1++;
311  if( *s1 == '\n' ) s1++;
312  else return( POLARSSL_ERR_PEM_INVALID_DATA );
313 #else
315 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
316  ( POLARSSL_AES_C || POLARSSL_DES_C ) */
317  }
318 
319  len = 0;
320  ret = base64_decode( NULL, &len, s1, s2 - s1 );
321 
323  return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
324 
325  if( ( buf = (unsigned char *) polarssl_malloc( len ) ) == NULL )
327 
328  if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
329  {
330  polarssl_free( buf );
331  return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
332  }
333 
334  if( enc != 0 )
335  {
336 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \
337  ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
338  if( pwd == NULL )
339  {
340  polarssl_free( buf );
342  }
343 
344 #if defined(POLARSSL_DES_C)
345  if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC )
346  pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
347  else if( enc_alg == POLARSSL_CIPHER_DES_CBC )
348  pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
349 #endif /* POLARSSL_DES_C */
350 
351 #if defined(POLARSSL_AES_C)
352  if( enc_alg == POLARSSL_CIPHER_AES_128_CBC )
353  pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
354  else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC )
355  pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
356  else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC )
357  pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
358 #endif /* POLARSSL_AES_C */
359 
360  /*
361  * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
362  * length bytes (allow 4 to be sure) in all known use cases.
363  *
364  * Use that as heurisitic to try detecting password mismatchs.
365  */
366  if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
367  {
368  polarssl_free( buf );
370  }
371 #else
372  polarssl_free( buf );
374 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
375  ( POLARSSL_AES_C || POLARSSL_DES_C ) */
376  }
377 
378  ctx->buf = buf;
379  ctx->buflen = len;
380 
381  return( 0 );
382 }
383 
384 void pem_free( pem_context *ctx )
385 {
386  polarssl_free( ctx->buf );
387  polarssl_free( ctx->info );
388 
389  polarssl_zeroize( ctx, sizeof( pem_context ) );
390 }
391 #endif /* POLARSSL_PEM_PARSE_C */
392 
393 #if defined(POLARSSL_PEM_WRITE_C)
394 int pem_write_buffer( const char *header, const char *footer,
395  const unsigned char *der_data, size_t der_len,
396  unsigned char *buf, size_t buf_len, size_t *olen )
397 {
398  int ret;
399  unsigned char *encode_buf, *c, *p = buf;
400  size_t len = 0, use_len = 0, add_len = 0;
401 
402  base64_encode( NULL, &use_len, der_data, der_len );
403  add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
404 
405  if( use_len + add_len > buf_len )
406  {
407  *olen = use_len + add_len;
409  }
410 
411  if( ( encode_buf = polarssl_malloc( use_len ) ) == NULL )
413 
414  if( ( ret = base64_encode( encode_buf, &use_len, der_data,
415  der_len ) ) != 0 )
416  {
417  polarssl_free( encode_buf );
418  return( ret );
419  }
420 
421  memcpy( p, header, strlen( header ) );
422  p += strlen( header );
423  c = encode_buf;
424 
425  while( use_len )
426  {
427  len = ( use_len > 64 ) ? 64 : use_len;
428  memcpy( p, c, len );
429  use_len -= len;
430  p += len;
431  c += len;
432  *p++ = '\n';
433  }
434 
435  memcpy( p, footer, strlen( footer ) );
436  p += strlen( footer );
437 
438  *p++ = '\0';
439  *olen = p - buf;
440 
441  polarssl_free( encode_buf );
442  return( 0 );
443 }
444 #endif /* POLARSSL_PEM_WRITE_C */
445 #endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */