Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pem.c
00001 /* 00002 * Privacy Enhanced Mail (PEM) decoding 00003 * 00004 * Copyright (C) 2006-2014, Brainspark B.V. 00005 * 00006 * This file is part of PolarSSL (http://www.polarssl.org) 00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> 00008 * 00009 * All rights reserved. 00010 * 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License along 00022 * with this program; if not, write to the Free Software Foundation, Inc., 00023 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00024 */ 00025 00026 #if !defined(POLARSSL_CONFIG_FILE) 00027 #include "polarssl/config.h" 00028 #else 00029 #include POLARSSL_CONFIG_FILE 00030 #endif 00031 00032 #if defined(POLARSSL_PEM_PARSE_C) || defined(POLARSSL_PEM_WRITE_C) 00033 #include "polarssl/pem.h" 00034 #include "polarssl/base64.h" 00035 #include "polarssl/des.h" 00036 #include "polarssl/aes.h" 00037 #include "polarssl/md5.h" 00038 #include "polarssl/cipher.h" 00039 00040 #if defined(POLARSSL_PLATFORM_C) 00041 #include "polarssl/platform.h" 00042 #else 00043 #define polarssl_malloc malloc 00044 #define polarssl_free free 00045 #endif 00046 00047 #include <stdlib.h> 00048 00049 #if defined(POLARSSL_PEM_PARSE_C) 00050 void pem_init( pem_context *ctx ) 00051 { 00052 memset( ctx, 0, sizeof( pem_context ) ); 00053 } 00054 00055 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ 00056 ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) 00057 /* 00058 * Read a 16-byte hex string and convert it to binary 00059 */ 00060 static int pem_get_iv( const unsigned char *s, unsigned char *iv, 00061 size_t iv_len ) 00062 { 00063 size_t i, j, k; 00064 00065 memset( iv, 0, iv_len ); 00066 00067 for( i = 0; i < iv_len * 2; i++, s++ ) 00068 { 00069 if( *s >= '0' && *s <= '9' ) j = *s - '0'; else 00070 if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else 00071 if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else 00072 return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); 00073 00074 k = ( ( i & 1 ) != 0 ) ? j : j << 4; 00075 00076 iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); 00077 } 00078 00079 return( 0 ); 00080 } 00081 00082 static void pem_pbkdf1( unsigned char *key, size_t keylen, 00083 unsigned char *iv, 00084 const unsigned char *pwd, size_t pwdlen ) 00085 { 00086 md5_context md5_ctx; 00087 unsigned char md5sum[16]; 00088 size_t use_len; 00089 00090 /* 00091 * key[ 0..15] = MD5(pwd || IV) 00092 */ 00093 md5_starts( &md5_ctx ); 00094 md5_update( &md5_ctx, pwd, pwdlen ); 00095 md5_update( &md5_ctx, iv, 8 ); 00096 md5_finish( &md5_ctx, md5sum ); 00097 00098 if( keylen <= 16 ) 00099 { 00100 memcpy( key, md5sum, keylen ); 00101 00102 memset( &md5_ctx, 0, sizeof( md5_ctx ) ); 00103 memset( md5sum, 0, 16 ); 00104 return; 00105 } 00106 00107 memcpy( key, md5sum, 16 ); 00108 00109 /* 00110 * key[16..23] = MD5(key[ 0..15] || pwd || IV]) 00111 */ 00112 md5_starts( &md5_ctx ); 00113 md5_update( &md5_ctx, md5sum, 16 ); 00114 md5_update( &md5_ctx, pwd, pwdlen ); 00115 md5_update( &md5_ctx, iv, 8 ); 00116 md5_finish( &md5_ctx, md5sum ); 00117 00118 use_len = 16; 00119 if( keylen < 32 ) 00120 use_len = keylen - 16; 00121 00122 memcpy( key + 16, md5sum, use_len ); 00123 00124 memset( &md5_ctx, 0, sizeof( md5_ctx ) ); 00125 memset( md5sum, 0, 16 ); 00126 } 00127 00128 #if defined(POLARSSL_DES_C) 00129 /* 00130 * Decrypt with DES-CBC, using PBKDF1 for key derivation 00131 */ 00132 static void pem_des_decrypt( unsigned char des_iv[8], 00133 unsigned char *buf, size_t buflen, 00134 const unsigned char *pwd, size_t pwdlen ) 00135 { 00136 des_context des_ctx; 00137 unsigned char des_key[8]; 00138 00139 pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); 00140 00141 des_setkey_dec( &des_ctx, des_key ); 00142 des_crypt_cbc( &des_ctx, DES_DECRYPT, buflen, 00143 des_iv, buf, buf ); 00144 00145 memset( &des_ctx, 0, sizeof( des_ctx ) ); 00146 memset( des_key, 0, 8 ); 00147 } 00148 00149 /* 00150 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation 00151 */ 00152 static void pem_des3_decrypt( unsigned char des3_iv[8], 00153 unsigned char *buf, size_t buflen, 00154 const unsigned char *pwd, size_t pwdlen ) 00155 { 00156 des3_context des3_ctx; 00157 unsigned char des3_key[24]; 00158 00159 pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); 00160 00161 des3_set3key_dec( &des3_ctx, des3_key ); 00162 des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen, 00163 des3_iv, buf, buf ); 00164 00165 memset( &des3_ctx, 0, sizeof( des3_ctx ) ); 00166 memset( des3_key, 0, 24 ); 00167 } 00168 #endif /* POLARSSL_DES_C */ 00169 00170 #if defined(POLARSSL_AES_C) 00171 /* 00172 * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation 00173 */ 00174 static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, 00175 unsigned char *buf, size_t buflen, 00176 const unsigned char *pwd, size_t pwdlen ) 00177 { 00178 aes_context aes_ctx; 00179 unsigned char aes_key[32]; 00180 00181 pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); 00182 00183 aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); 00184 aes_crypt_cbc( &aes_ctx, AES_DECRYPT, buflen, 00185 aes_iv, buf, buf ); 00186 00187 memset( &aes_ctx, 0, sizeof( aes_ctx ) ); 00188 memset( aes_key, 0, keylen ); 00189 } 00190 #endif /* POLARSSL_AES_C */ 00191 00192 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && 00193 ( POLARSSL_AES_C || POLARSSL_DES_C ) */ 00194 00195 int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, 00196 const unsigned char *data, const unsigned char *pwd, 00197 size_t pwdlen, size_t *use_len ) 00198 { 00199 int ret, enc; 00200 size_t len; 00201 unsigned char *buf; 00202 const unsigned char *s1, *s2, *end; 00203 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ 00204 ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) 00205 unsigned char pem_iv[16]; 00206 cipher_type_t enc_alg = POLARSSL_CIPHER_NONE; 00207 #else 00208 ((void) pwd); 00209 ((void) pwdlen); 00210 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && 00211 ( POLARSSL_AES_C || POLARSSL_DES_C ) */ 00212 00213 if( ctx == NULL ) 00214 return( POLARSSL_ERR_PEM_BAD_INPUT_DATA ); 00215 00216 s1 = (unsigned char *) strstr( (const char *) data, header ); 00217 00218 if( s1 == NULL ) 00219 return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); 00220 00221 s2 = (unsigned char *) strstr( (const char *) data, footer ); 00222 00223 if( s2 == NULL || s2 <= s1 ) 00224 return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); 00225 00226 s1 += strlen( header ); 00227 if( *s1 == '\r' ) s1++; 00228 if( *s1 == '\n' ) s1++; 00229 else return( POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); 00230 00231 end = s2; 00232 end += strlen( footer ); 00233 if( *end == '\r' ) end++; 00234 if( *end == '\n' ) end++; 00235 *use_len = end - data; 00236 00237 enc = 0; 00238 00239 if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) 00240 { 00241 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ 00242 ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) 00243 enc++; 00244 00245 s1 += 22; 00246 if( *s1 == '\r' ) s1++; 00247 if( *s1 == '\n' ) s1++; 00248 else return( POLARSSL_ERR_PEM_INVALID_DATA ); 00249 00250 00251 #if defined(POLARSSL_DES_C) 00252 if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) 00253 { 00254 enc_alg = POLARSSL_CIPHER_DES_EDE3_CBC; 00255 00256 s1 += 23; 00257 if( pem_get_iv( s1, pem_iv, 8 ) != 0 ) 00258 return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); 00259 00260 s1 += 16; 00261 } 00262 else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) 00263 { 00264 enc_alg = POLARSSL_CIPHER_DES_CBC; 00265 00266 s1 += 18; 00267 if( pem_get_iv( s1, pem_iv, 8) != 0 ) 00268 return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); 00269 00270 s1 += 16; 00271 } 00272 #endif /* POLARSSL_DES_C */ 00273 00274 #if defined(POLARSSL_AES_C) 00275 if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) 00276 { 00277 if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) 00278 enc_alg = POLARSSL_CIPHER_AES_128_CBC; 00279 else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) 00280 enc_alg = POLARSSL_CIPHER_AES_192_CBC; 00281 else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) 00282 enc_alg = POLARSSL_CIPHER_AES_256_CBC; 00283 else 00284 return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG ); 00285 00286 s1 += 22; 00287 if( pem_get_iv( s1, pem_iv, 16 ) != 0 ) 00288 return( POLARSSL_ERR_PEM_INVALID_ENC_IV ); 00289 00290 s1 += 32; 00291 } 00292 #endif /* POLARSSL_AES_C */ 00293 00294 if( enc_alg == POLARSSL_CIPHER_NONE ) 00295 return( POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG ); 00296 00297 if( *s1 == '\r' ) s1++; 00298 if( *s1 == '\n' ) s1++; 00299 else return( POLARSSL_ERR_PEM_INVALID_DATA ); 00300 #else 00301 return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE ); 00302 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && 00303 ( POLARSSL_AES_C || POLARSSL_DES_C ) */ 00304 } 00305 00306 len = 0; 00307 ret = base64_decode( NULL, &len, s1, s2 - s1 ); 00308 00309 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER ) 00310 return( POLARSSL_ERR_PEM_INVALID_DATA + ret ); 00311 00312 if( ( buf = (unsigned char *) polarssl_malloc( len ) ) == NULL ) 00313 return( POLARSSL_ERR_PEM_MALLOC_FAILED ); 00314 00315 if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 ) 00316 { 00317 polarssl_free( buf ); 00318 return( POLARSSL_ERR_PEM_INVALID_DATA + ret ); 00319 } 00320 00321 if( enc != 0 ) 00322 { 00323 #if defined(POLARSSL_MD5_C) && defined(POLARSSL_CIPHER_MODE_CBC) && \ 00324 ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) 00325 if( pwd == NULL ) 00326 { 00327 polarssl_free( buf ); 00328 return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED ); 00329 } 00330 00331 #if defined(POLARSSL_DES_C) 00332 if( enc_alg == POLARSSL_CIPHER_DES_EDE3_CBC ) 00333 pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); 00334 else if( enc_alg == POLARSSL_CIPHER_DES_CBC ) 00335 pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); 00336 #endif /* POLARSSL_DES_C */ 00337 00338 #if defined(POLARSSL_AES_C) 00339 if( enc_alg == POLARSSL_CIPHER_AES_128_CBC ) 00340 pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); 00341 else if( enc_alg == POLARSSL_CIPHER_AES_192_CBC ) 00342 pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); 00343 else if( enc_alg == POLARSSL_CIPHER_AES_256_CBC ) 00344 pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); 00345 #endif /* POLARSSL_AES_C */ 00346 00347 /* 00348 * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 00349 * length bytes (allow 4 to be sure) in all known use cases. 00350 * 00351 * Use that as heurisitic to try detecting password mismatchs. 00352 */ 00353 if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) 00354 { 00355 polarssl_free( buf ); 00356 return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH ); 00357 } 00358 #else 00359 polarssl_free( buf ); 00360 return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE ); 00361 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && 00362 ( POLARSSL_AES_C || POLARSSL_DES_C ) */ 00363 } 00364 00365 ctx->buf = buf; 00366 ctx->buflen = len; 00367 00368 return( 0 ); 00369 } 00370 00371 void pem_free( pem_context *ctx ) 00372 { 00373 if( ctx->buf ) 00374 polarssl_free( ctx->buf ); 00375 00376 if( ctx->info ) 00377 polarssl_free( ctx->info ); 00378 00379 memset( ctx, 0, sizeof( pem_context ) ); 00380 } 00381 #endif /* POLARSSL_PEM_PARSE_C */ 00382 00383 #if defined(POLARSSL_PEM_WRITE_C) 00384 int pem_write_buffer( const char *header, const char *footer, 00385 const unsigned char *der_data, size_t der_len, 00386 unsigned char *buf, size_t buf_len, size_t *olen ) 00387 { 00388 int ret; 00389 unsigned char *encode_buf, *c, *p = buf; 00390 size_t len = 0, use_len = 0, add_len = 0; 00391 00392 base64_encode( NULL, &use_len, der_data, der_len ); 00393 add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; 00394 00395 if( use_len + add_len > buf_len ) 00396 { 00397 *olen = use_len + add_len; 00398 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); 00399 } 00400 00401 if( ( encode_buf = polarssl_malloc( use_len ) ) == NULL ) 00402 return( POLARSSL_ERR_PEM_MALLOC_FAILED ); 00403 00404 if( ( ret = base64_encode( encode_buf, &use_len, der_data, 00405 der_len ) ) != 0 ) 00406 { 00407 polarssl_free( encode_buf ); 00408 return( ret ); 00409 } 00410 00411 memcpy( p, header, strlen( header ) ); 00412 p += strlen( header ); 00413 c = encode_buf; 00414 00415 while( use_len ) 00416 { 00417 len = ( use_len > 64 ) ? 64 : use_len; 00418 memcpy( p, c, len ); 00419 use_len -= len; 00420 p += len; 00421 c += len; 00422 *p++ = '\n'; 00423 } 00424 00425 memcpy( p, footer, strlen( footer ) ); 00426 p += strlen( footer ); 00427 00428 *p++ = '\0'; 00429 *olen = p - buf; 00430 00431 polarssl_free( encode_buf ); 00432 return( 0 ); 00433 } 00434 #endif /* POLARSSL_PEM_WRITE_C */ 00435 #endif /* POLARSSL_PEM_PARSE_C || POLARSSL_PEM_WRITE_C */ 00436 00437
Generated on Tue Jul 12 2022 19:40:19 by
1.7.2