int PBKDF2_HMAC_SHA_1_string(const char* pass, const unsigned char* salt, int32_t iterations, uint32_t outputBytes, char* hexResult) { md_context_t sha1_ctx; const md_info_t *info_sha1; int ret, i; unsigned char digest[outputBytes]; // credit to https://github.com/polarssl/polarssl/blob/development/library/pkcs5.c pkcs5_self_test info_sha1 = md_info_from_type( POLARSSL_MD_SHA1 ); if( info_sha1 == NULL ) return( 104 ); if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 ) return( 103 ); ret = pkcs5_pbkdf2_hmac( &sha1_ctx, pass, strlen(pass), salt, strlen(salt), iterations, outputBytes, digest ); if( ret != 0 ) { return( 102 ); } if( ( ret = md_free_ctx( &sha1_ctx ) ) != 0 ) return( 101 ); for (i = 0; i < sizeof(digest); i++) sprintf(hexResult + (i * 2), "%02x", 255 & digest[i]); return(0); }
/* * Helper for writing signature algorithms */ int x509_sig_alg_gets( char *buf, size_t size, const x509_buf *sig_oid, pk_type_t pk_alg, md_type_t md_alg, const void *sig_opts ) { int ret; char *p = buf; size_t n = size; const char *desc = NULL; ret = oid_get_sig_alg_desc( sig_oid, &desc ); if( ret != 0 ) ret = polarssl_snprintf( p, n, "???" ); else ret = polarssl_snprintf( p, n, "%s", desc ); SAFE_SNPRINTF(); #if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) if( pk_alg == POLARSSL_PK_RSASSA_PSS ) { const pk_rsassa_pss_options *pss_opts; const md_info_t *md_info, *mgf_md_info; pss_opts = (const pk_rsassa_pss_options *) sig_opts; md_info = md_info_from_type( md_alg ); mgf_md_info = md_info_from_type( pss_opts->mgf1_hash_id ); ret = polarssl_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", md_info ? md_info->name : "???", mgf_md_info ? mgf_md_info->name : "???", pss_opts->expected_salt_len ); SAFE_SNPRINTF(); } #else ((void) pk_alg); ((void) md_alg); ((void) sig_opts); #endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */ return( (int)( size - n ) ); }
/* * Helper for pk_sign and pk_verify */ static inline int pk_hashlen_helper( md_type_t md_alg, size_t *hash_len ) { const md_info_t *md_info; if( *hash_len != 0 ) return( 0 ); if( ( md_info = md_info_from_type( md_alg ) ) == NULL ) return( -1 ); *hash_len = md_info->size; return( 0 ); }
/* * Checkup routine for HMAC_DRBG with SHA-1 */ SSL_ROM_TEXT_SECTION int hmac_drbg_self_test( int verbose ) { hmac_drbg_context ctx; unsigned char buf[OUTPUT_LEN]; const md_info_t *md_info = md_info_from_type( POLARSSL_MD_SHA1 ); /* * PR = True */ if( verbose != 0 ) polarssl_printf( " HMAC_DRBG (PR = True) : " ); test_offset = 0; CHK( hmac_drbg_init( &ctx, md_info, hmac_drbg_self_test_entropy, entropy_pr, NULL, 0 ) ); hmac_drbg_set_prediction_resistance( &ctx, POLARSSL_HMAC_DRBG_PR_ON ); CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); hmac_drbg_free( &ctx ); if( verbose != 0 ) polarssl_printf( "passed\n" ); /* * PR = False */ if( verbose != 0 ) polarssl_printf( " HMAC_DRBG (PR = False) : " ); test_offset = 0; CHK( hmac_drbg_init( &ctx, md_info, hmac_drbg_self_test_entropy, entropy_nopr, NULL, 0 ) ); CHK( hmac_drbg_reseed( &ctx, NULL, 0 ) ); CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); CHK( hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); hmac_drbg_free( &ctx ); if( verbose != 0 ) polarssl_printf( "passed\n" ); if( verbose != 0 ) polarssl_printf( "\n" ); return( 0 ); }
SSL_ROM_TEXT_SECTION const md_info_t *md_info_from_string( const char *md_name ) { if( NULL == md_name ) return( NULL ); /* Get the appropriate digest information */ #if defined(POLARSSL_MD2_C) if( !strcasecmp( "MD2", md_name ) ) return md_info_from_type( POLARSSL_MD_MD2 ); #endif #if defined(POLARSSL_MD4_C) if( !strcasecmp( "MD4", md_name ) ) return md_info_from_type( POLARSSL_MD_MD4 ); #endif #if defined(POLARSSL_MD5_C) if( !strcasecmp( "MD5", md_name ) ) return md_info_from_type( POLARSSL_MD_MD5 ); #endif #if defined(POLARSSL_RIPEMD160_C) if( !strcasecmp( "RIPEMD160", md_name ) ) return md_info_from_type( POLARSSL_MD_RIPEMD160 ); #endif #if defined(POLARSSL_SHA1_C) if( !strcasecmp( "SHA1", md_name ) || !strcasecmp( "SHA", md_name ) ) return md_info_from_type( POLARSSL_MD_SHA1 ); #endif #if defined(POLARSSL_SHA256_C) if( !strcasecmp( "SHA224", md_name ) ) return md_info_from_type( POLARSSL_MD_SHA224 ); if( !strcasecmp( "SHA256", md_name ) ) return md_info_from_type( POLARSSL_MD_SHA256 ); #endif #if defined(POLARSSL_SHA512_C) if( !strcasecmp( "SHA384", md_name ) ) return md_info_from_type( POLARSSL_MD_SHA384 ); if( !strcasecmp( "SHA512", md_name ) ) return md_info_from_type( POLARSSL_MD_SHA512 ); #endif return( NULL ); }
bool gtkhash_hash_lib_polarssl_is_supported(const enum hash_func_e id) { struct hash_lib_polarssl_s data; md_type_t type; if (!gtkhash_hash_lib_polarssl_set_type(id, &type)) return false; if (md_init_ctx(&data.ctx, md_info_from_type(type)) != 0) return false; if (md_free_ctx(&data.ctx) != 0) { g_assert_not_reached(); return false; } return true; }
int pkcs5_self_test( int verbose ) { md_context_t sha1_ctx; const md_info_t *info_sha1; int ret, i; unsigned char key[64]; info_sha1 = md_info_from_type( POLARSSL_MD_SHA1 ); if( info_sha1 == NULL ) return( 1 ); if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 ) return( 1 ); for( i = 0; i < MAX_TESTS; i++ ) { printf( " PBKDF2 (SHA1) #%d: ", i ); ret = pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], slen[i], it_cnt[i], key_len[i], key ); if( ret != 0 || memcmp( result_key[i], key, key_len[i] ) != 0 ) { if( verbose != 0 ) printf( "failed\n" ); return( 1 ); } if( verbose != 0 ) printf( "passed\n" ); } printf( "\n" ); return( 0 ); }
void show_available_digests () { const int *digests = md_list(); #ifndef ENABLE_SMALL printf ("The following message digests are available for use with\n" PACKAGE_NAME ". A message digest is used in conjunction with\n" "the HMAC function, to authenticate received packets.\n" "You can specify a message digest as parameter to\n" "the --auth option.\n\n"); #endif while (*digests != 0) { const md_info_t *info = md_info_from_type(*digests); if (info && is_allowed_data_channel_digest(info->name)) printf ("%s %d bit default key\n", info->name, info->size * 8); digests++; } printf ("\n"); }
/* * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function */ int rsa_rsaes_oaep_decrypt( rsa_context *ctx, int mode, const unsigned char *label, size_t label_len, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len ) { int ret; size_t ilen; unsigned char *p; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; unsigned char lhash[POLARSSL_MD_MAX_SIZE]; unsigned int hlen; const md_info_t *md_info; md_context_t md_ctx; if( ctx->padding != RSA_PKCS_V21 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); ilen = ctx->len; if( ilen < 16 || ilen > sizeof( buf ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); ret = ( mode == RSA_PUBLIC ) ? rsa_public( ctx, input, buf ) : rsa_private( ctx, input, buf ); if( ret != 0 ) return( ret ); p = buf; if( *p++ != 0 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); md_info = md_info_from_type( ctx->hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hlen = md_get_size( md_info ); md_init_ctx( &md_ctx, md_info ); // Generate lHash // md( md_info, label, label_len, lhash ); // seed: Apply seedMask to maskedSeed // mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, &md_ctx ); // DB: Apply dbMask to maskedDB // mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, &md_ctx ); p += hlen; md_free_ctx( &md_ctx ); // Check validity // if( memcmp( lhash, p, hlen ) != 0 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); p += hlen; while( *p == 0 && p < buf + ilen ) p++; if( p == buf + ilen ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if( *p++ != 0x01 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if (ilen - (p - buf) > output_max_len) return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); *olen = ilen - (p - buf); memcpy( output, p, *olen ); return( 0 ); }
/* * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function */ int rsa_rsaes_oaep_encrypt( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, const unsigned char *label, size_t label_len, size_t ilen, const unsigned char *input, unsigned char *output ) { size_t olen; int ret; unsigned char *p = output; unsigned int hlen; const md_info_t *md_info; md_context_t md_ctx; if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); md_info = md_info_from_type( ctx->hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); olen = ctx->len; hlen = md_get_size( md_info ); if( olen < ilen + 2 * hlen + 2 || f_rng == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); memset( output, 0, olen ); *p++ = 0; // Generate a random octet string seed // if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); p += hlen; // Construct DB // md( md_info, label, label_len, p ); p += hlen; p += olen - 2 * hlen - 2 - ilen; *p++ = 1; memcpy( p, input, ilen ); md_init_ctx( &md_ctx, md_info ); // maskedDB: Apply dbMask to DB // mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, &md_ctx ); // maskedSeed: Apply seedMask to seed // mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, &md_ctx ); md_free_ctx( &md_ctx ); return( ( mode == RSA_PUBLIC ) ? rsa_public( ctx, output, output ) : rsa_private( ctx, output, output ) ); }
/* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function */ int rsa_rsassa_pss_verify( rsa_context *ctx, int mode, int hash_id, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ) { int ret; size_t siglen; unsigned char *p; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; unsigned char result[POLARSSL_MD_MAX_SIZE]; unsigned char zeros[8]; unsigned int hlen; size_t slen, msb; const md_info_t *md_info; md_context_t md_ctx; if( ctx->padding != RSA_PKCS_V21 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); siglen = ctx->len; if( siglen < 16 || siglen > sizeof( buf ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); ret = ( mode == RSA_PUBLIC ) ? rsa_public( ctx, sig, buf ) : rsa_private( ctx, sig, buf ); if( ret != 0 ) return( ret ); p = buf; if( buf[siglen - 1] != 0xBC ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); switch( hash_id ) { case SIG_RSA_MD2: case SIG_RSA_MD4: case SIG_RSA_MD5: hashlen = 16; break; case SIG_RSA_SHA1: hashlen = 20; break; case SIG_RSA_SHA224: hashlen = 28; break; case SIG_RSA_SHA256: hashlen = 32; break; case SIG_RSA_SHA384: hashlen = 48; break; case SIG_RSA_SHA512: hashlen = 64; break; default: return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } md_info = md_info_from_type( ctx->hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hlen = md_get_size( md_info ); slen = siglen - hlen - 1; memset( zeros, 0, 8 ); // Note: EMSA-PSS verification is over the length of N - 1 bits // msb = mpi_msb( &ctx->N ) - 1; // Compensate for boundary condition when applying mask // if( msb % 8 == 0 ) { p++; siglen -= 1; } if( buf[0] >> ( 8 - siglen * 8 + msb ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); md_init_ctx( &md_ctx, md_info ); mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); buf[0] &= 0xFF >> ( siglen * 8 - msb ); while( *p == 0 && p < buf + siglen ) p++; if( p == buf + siglen || *p++ != 0x01 ) { md_free_ctx( &md_ctx ); return( POLARSSL_ERR_RSA_INVALID_PADDING ); } slen -= p - buf; // Generate H = Hash( M' ) // md_starts( &md_ctx ); md_update( &md_ctx, zeros, 8 ); md_update( &md_ctx, hash, hashlen ); md_update( &md_ctx, p, slen ); md_finish( &md_ctx, result ); md_free_ctx( &md_ctx ); if( memcmp( p + slen, result, hlen ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); }
/* * Do an RSA operation and check the message digest */ int rsa_pkcs1_verify( rsa_context *ctx, int mode, int hash_id, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ) { int ret; size_t len, siglen; unsigned char *p, c; unsigned char buf[1024]; #if defined(POLARSSL_PKCS1_V21) unsigned char zeros[8]; unsigned int hlen; size_t slen, msb; const md_info_t *md_info; md_context_t md_ctx; #endif siglen = ctx->len; if( siglen < 16 || siglen > (int) sizeof( buf ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); ret = ( mode == RSA_PUBLIC ) ? rsa_public( ctx, sig, buf ) : rsa_private( ctx, sig, buf ); if( ret != 0 ) return( ret ); p = buf; switch( ctx->padding ) { case RSA_PKCS_V15: if( *p++ != 0 || *p++ != RSA_SIGN ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); while( *p != 0 ) { if( p >= buf + siglen - 1 || *p != 0xFF ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); p++; } p++; len = siglen - (int)( p - buf ); if( len == 34 ) { c = p[13]; p[13] = 0; if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( ( c == 2 && hash_id == SIG_RSA_MD2 ) || ( c == 4 && hash_id == SIG_RSA_MD4 ) || ( c == 5 && hash_id == SIG_RSA_MD5 ) ) { if( memcmp( p + 18, hash, 16 ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); } } if( len == 35 && hash_id == SIG_RSA_SHA1 ) { if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 && memcmp( p + 15, hash, 20 ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); } if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) || ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) || ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) || ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) ) { c = p[1] - 17; p[1] = 17; p[14] = 0; if( p[18] == c && memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 && memcmp( p + 19, hash, c ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); } if( len == hashlen && hash_id == SIG_RSA_RAW ) { if( memcmp( p, hash, hashlen ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); } break; #if defined(POLARSSL_PKCS1_V21) case RSA_PKCS_V21: if( buf[siglen - 1] != 0xBC ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); switch( hash_id ) { case SIG_RSA_MD2: case SIG_RSA_MD4: case SIG_RSA_MD5: hashlen = 16; break; case SIG_RSA_SHA1: hashlen = 20; break; case SIG_RSA_SHA224: hashlen = 28; break; case SIG_RSA_SHA256: hashlen = 32; break; case SIG_RSA_SHA384: hashlen = 48; break; case SIG_RSA_SHA512: hashlen = 64; break; default: return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } md_info = md_info_from_type( ctx->hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hlen = md_get_size( md_info ); slen = siglen - hlen - 1; memset( &md_ctx, 0, sizeof( md_context_t ) ); memset( zeros, 0, 8 ); md_init_ctx( &md_ctx, md_info ); // Note: EMSA-PSS verification is over the length of N - 1 bits // msb = mpi_msb( &ctx->N ) - 1; // Compensate for boundary condition when applying mask // if( msb % 8 == 0 ) { p++; siglen -= 1; } if( buf[0] >> ( 8 - siglen * 8 + msb ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); buf[0] &= 0xFF >> ( siglen * 8 - msb ); while( *p == 0 && p < buf + siglen ) p++; if( p == buf + siglen ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if( *p++ != 0x01 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); slen -= p - buf; // Generate H = Hash( M' ) // md_starts( &md_ctx ); md_update( &md_ctx, zeros, 8 ); md_update( &md_ctx, hash, hashlen ); md_update( &md_ctx, p, slen ); md_finish( &md_ctx, p ); if( memcmp( p, p + slen, hlen ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); break; #endif default: return( POLARSSL_ERR_RSA_INVALID_PADDING ); } return( POLARSSL_ERR_RSA_INVALID_PADDING ); }
/* * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function */ int rsa_rsaes_oaep_decrypt( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, const unsigned char *label, size_t label_len, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len ) { int ret; size_t ilen, i, pad_len; unsigned char *p, bad, pad_done; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; unsigned char lhash[POLARSSL_MD_MAX_SIZE]; unsigned int hlen; const md_info_t *md_info; md_context_t md_ctx; /* * Parameters sanity checks */ if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); ilen = ctx->len; if( ilen < 16 || ilen > sizeof( buf ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); md_info = md_info_from_type( ctx->hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); /* * RSA operation */ ret = ( mode == RSA_PUBLIC ) ? rsa_public( ctx, input, buf ) : rsa_private( ctx, f_rng, p_rng, input, buf ); if( ret != 0 ) return( ret ); /* * Unmask data and generate lHash */ hlen = md_get_size( md_info ); md_init( &md_ctx ); md_init_ctx( &md_ctx, md_info ); /* Generate lHash */ md( md_info, label, label_len, lhash ); /* seed: Apply seedMask to maskedSeed */ mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, &md_ctx ); /* DB: Apply dbMask to maskedDB */ mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, &md_ctx ); md_free( &md_ctx ); /* * Check contents, in "constant-time" */ p = buf; bad = 0; bad |= *p++; /* First byte must be 0 */ p += hlen; /* Skip seed */ /* Check lHash */ for( i = 0; i < hlen; i++ ) bad |= lhash[i] ^ *p++; /* Get zero-padding len, but always read till end of buffer * (minus one, for the 01 byte) */ pad_len = 0; pad_done = 0; for( i = 0; i < ilen - 2 * hlen - 2; i++ ) { pad_done |= p[i]; pad_len += ( pad_done == 0 ); } p += pad_len; bad |= *p++ ^ 0x01; /* * The only information "leaked" is whether the padding was correct or not * (eg, no data is copied if it was not correct). This meets the * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between * the different error conditions. */ if( bad != 0 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if( ilen - ( p - buf ) > output_max_len ) return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); *olen = ilen - (p - buf); memcpy( output, p, *olen ); return( 0 ); }
static int x509_crt_verify_top( x509_crt *child, x509_crt *trust_ca, x509_crl *ca_crl, int path_cnt, int *flags, int (*f_vrfy)(void *, x509_crt *, int, int *), void *p_vrfy ) { int ret; int ca_flags = 0, check_path_cnt = path_cnt + 1; unsigned char hash[POLARSSL_MD_MAX_SIZE]; const md_info_t *md_info; if( x509_time_expired( &child->valid_to ) ) *flags |= BADCERT_EXPIRED; /* * Child is the top of the chain. Check against the trust_ca list. */ *flags |= BADCERT_NOT_TRUSTED; md_info = md_info_from_type( child->sig_md ); if( md_info == NULL ) { /* * Cannot check 'unknown', no need to try any CA */ trust_ca = NULL; } else md( md_info, child->tbs.p, child->tbs.len, hash ); while( trust_ca != NULL ) { if( trust_ca->version == 0 || child->issuer_raw.len != trust_ca->subject_raw.len || memcmp( child->issuer_raw.p, trust_ca->subject_raw.p, child->issuer_raw.len ) != 0 ) { trust_ca = trust_ca->next; continue; } /* * Reduce path_len to check against if top of the chain is * the same as the trusted CA */ if( child->subject_raw.len == trust_ca->subject_raw.len && memcmp( child->subject_raw.p, trust_ca->subject_raw.p, child->issuer_raw.len ) == 0 ) { check_path_cnt--; } if( trust_ca->max_pathlen > 0 && trust_ca->max_pathlen < check_path_cnt ) { trust_ca = trust_ca->next; continue; } if( pk_can_do( &trust_ca->pk, child->sig_pk ) == 0 || pk_verify( &trust_ca->pk, child->sig_md, hash, md_info->size, child->sig.p, child->sig.len ) != 0 ) { trust_ca = trust_ca->next; continue; } /* * Top of chain is signed by a trusted CA */ *flags &= ~BADCERT_NOT_TRUSTED; break; } /* * If top of chain is not the same as the trusted CA send a verify request * to the callback for any issues with validity and CRL presence for the * trusted CA certificate. */ if( trust_ca != NULL && ( child->subject_raw.len != trust_ca->subject_raw.len || memcmp( child->subject_raw.p, trust_ca->subject_raw.p, child->issuer_raw.len ) != 0 ) ) { #if defined(POLARSSL_X509_CRL_PARSE_C) /* Check trusted CA's CRL for the chain's top crt */ *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl ); #else ((void) ca_crl); #endif if( x509_time_expired( &trust_ca->valid_to ) ) ca_flags |= BADCERT_EXPIRED; if( NULL != f_vrfy ) { if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, &ca_flags ) ) != 0 ) return( ret ); } } /* Call callback on top cert */ if( NULL != f_vrfy ) { if( ( ret = f_vrfy(p_vrfy, child, path_cnt, flags ) ) != 0 ) return( ret ); } *flags |= ca_flags; return( 0 ); }
int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[64]; unsigned char sig[POLARSSL_MPI_MAX_SIZE]; unsigned char tmp_buf[2048]; size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; pk_type_t pk_alg; /* * Prepare data to be signed in tmp_buf */ c = tmp_buf + sizeof( tmp_buf ); ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); if( len ) { ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) ); ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ, OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); } ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ); ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key, tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; /* * Subject ::= Name */ ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); /* * Prepare signature */ md( md_info_from_type( ctx->md_alg ), c, len, hash ); if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 ) { return( ret ); } if( pk_can_do( ctx->key, POLARSSL_PK_RSA ) ) pk_alg = POLARSSL_PK_RSA; else if( pk_can_do( ctx->key, POLARSSL_PK_ECDSA ) ) pk_alg = POLARSSL_PK_ECDSA; else return( POLARSSL_ERR_X509_INVALID_ALG ); if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len ) ) != 0 ) { return( ret ); } /* * Write data to output buffer */ c2 = buf + size; ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, sig, sig_len ) ); if( len > (size_t)( c2 - buf ) ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); c2 -= len; memcpy( c2, c, len ); len += sig_and_oid_len; ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); return( (int) len ); }
/* * Check that the given certificate is valid according to the CRL. */ static int x509_crt_verifycrl( x509_crt *crt, x509_crt *ca, x509_crl *crl_list) { int flags = 0; unsigned char hash[POLARSSL_MD_MAX_SIZE]; const md_info_t *md_info; if( ca == NULL ) return( flags ); /* * TODO: What happens if no CRL is present? * Suggestion: Revocation state should be unknown if no CRL is present. * For backwards compatibility this is not yet implemented. */ while( crl_list != NULL ) { if( crl_list->version == 0 || crl_list->issuer_raw.len != ca->subject_raw.len || memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, crl_list->issuer_raw.len ) != 0 ) { crl_list = crl_list->next; continue; } /* * Check if CRL is correctly signed by the trusted CA */ md_info = md_info_from_type( crl_list->sig_md ); if( md_info == NULL ) { /* * Cannot check 'unknown' hash */ flags |= BADCRL_NOT_TRUSTED; break; } md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); if( pk_can_do( &ca->pk, crl_list->sig_pk ) == 0 || pk_verify( &ca->pk, crl_list->sig_md, hash, md_info->size, crl_list->sig.p, crl_list->sig.len ) != 0 ) { flags |= BADCRL_NOT_TRUSTED; break; } /* * Check for validity of CRL (Do not drop out) */ if( x509_time_expired( &crl_list->next_update ) ) flags |= BADCRL_EXPIRED; /* * Check if certificate is revoked */ if( x509_crt_revoked(crt, crl_list) ) { flags |= BADCERT_REVOKED; break; } crl_list = crl_list->next; } return flags; }
int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[64]; unsigned char sig[POLARSSL_MPI_MAX_SIZE]; unsigned char tmp_buf[2048]; size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; pk_type_t pk_alg; /* * Prepare data to be signed in tmp_buf */ c = tmp_buf + sizeof( tmp_buf ); /* Signature algorithm needed in TBS, and later for actual signature */ pk_alg = pk_get_type( ctx->issuer_key ); if( pk_alg == POLARSSL_PK_ECKEY ) pk_alg = POLARSSL_PK_ECDSA; if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len ) ) != 0 ) { return( ret ); } /* * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ); /* * SubjectPublicKeyInfo */ ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->subject_key, tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; /* * Subject ::= Name */ ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } */ sub_len = 0; ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, X509_RFC5280_UTC_TIME_LEN ) ); ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, X509_RFC5280_UTC_TIME_LEN ) ); len += sub_len; ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); /* * Issuer ::= Name */ ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) ); /* * Signature ::= AlgorithmIdentifier */ ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf, sig_oid, strlen( sig_oid ), 0 ) ); /* * Serial ::= INTEGER */ ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ sub_len = 0; ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) ); len += sub_len; ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); /* * Make signature */ md( md_info_from_type( ctx->md_alg ), c, len, hash ); if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 ) { return( ret ); } /* * Write data to output buffer */ c2 = buf + size; ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, sig, sig_len ) ); c2 -= len; memcpy( c2, c, len ); len += sig_and_oid_len; ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); return( (int) len ); }
/* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function */ int rsa_rsassa_pss_verify_ext( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, md_type_t mgf1_hash_id, int expected_salt_len, const unsigned char *sig ) { int ret; size_t siglen; unsigned char *p; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; unsigned char result[POLARSSL_MD_MAX_SIZE]; unsigned char zeros[8]; unsigned int hlen; size_t slen, msb; const md_info_t *md_info; md_context_t md_ctx; if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V21 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); siglen = ctx->len; if( siglen < 16 || siglen > sizeof( buf ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); ret = ( mode == RSA_PUBLIC ) ? rsa_public( ctx, sig, buf ) : rsa_private( ctx, f_rng, p_rng, sig, buf ); if( ret != 0 ) return( ret ); p = buf; if( buf[siglen - 1] != 0xBC ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if( md_alg != POLARSSL_MD_NONE ) { // Gather length of hash to sign // md_info = md_info_from_type( md_alg ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hashlen = md_get_size( md_info ); } md_info = md_info_from_type( mgf1_hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hlen = md_get_size( md_info ); slen = siglen - hlen - 1; /* Currently length of salt + padding */ memset( zeros, 0, 8 ); // Note: EMSA-PSS verification is over the length of N - 1 bits // msb = mpi_msb( &ctx->N ) - 1; // Compensate for boundary condition when applying mask // if( msb % 8 == 0 ) { p++; siglen -= 1; } if( buf[0] >> ( 8 - siglen * 8 + msb ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); md_init( &md_ctx ); md_init_ctx( &md_ctx, md_info ); mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); buf[0] &= 0xFF >> ( siglen * 8 - msb ); while( p < buf + siglen && *p == 0 ) p++; if( p == buf + siglen || *p++ != 0x01 ) { md_free( &md_ctx ); return( POLARSSL_ERR_RSA_INVALID_PADDING ); } /* Actual salt len */ slen -= p - buf; if( expected_salt_len != RSA_SALT_LEN_ANY && slen != (size_t) expected_salt_len ) { md_free( &md_ctx ); return( POLARSSL_ERR_RSA_INVALID_PADDING ); } // Generate H = Hash( M' ) // md_starts( &md_ctx ); md_update( &md_ctx, zeros, 8 ); md_update( &md_ctx, hash, hashlen ); md_update( &md_ctx, p, slen ); md_finish( &md_ctx, result ); md_free( &md_ctx ); if( memcmp( p + slen, result, hlen ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); }
int pkcs5_pbes2( asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output ) { int ret, iterations = 0, keylen = 0; unsigned char *p, *end, *end2; asn1_buf kdf_alg_oid, enc_scheme_oid, salt; md_type_t md_type = POLARSSL_MD_SHA1; unsigned char key[32], iv[32]; size_t len = 0, olen = 0; const md_info_t *md_info; const cipher_info_t *cipher_info; md_context_t md_ctx; cipher_context_t cipher_ctx; p = pbe_params->p; end = p + pbe_params->len; /* * PBES2-params ::= SEQUENCE { * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); } if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); } end2 = p + len; if( ( ret = asn1_get_tag( &p, end2, &kdf_alg_oid.len, ASN1_OID ) ) != 0 ) return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); kdf_alg_oid.p = p; p += kdf_alg_oid.len; // Only PBKDF2 supported at the moment // if( !OID_CMP( OID_PKCS5_PBKDF2, &kdf_alg_oid ) ) return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); if( ( ret = pkcs5_parse_pbkdf2_params( &p, end2, &salt, &iterations, &keylen, &md_type ) ) != 0 ) { return( ret ); } md_info = md_info_from_type( md_type ); if( md_info == NULL ) return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); } end2 = p + len; if( ( ret = asn1_get_tag( &p, end2, &enc_scheme_oid.len, ASN1_OID ) ) != 0 ) return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); enc_scheme_oid.p = p; p += enc_scheme_oid.len; #if defined(POLARSSL_DES_C) // Only DES-CBC and DES-EDE3-CBC supported at the moment // if( OID_CMP( OID_DES_EDE3_CBC, &enc_scheme_oid ) ) { cipher_info = cipher_info_from_type( POLARSSL_CIPHER_DES_EDE3_CBC ); } else if( OID_CMP( OID_DES_CBC, &enc_scheme_oid ) ) { cipher_info = cipher_info_from_type( POLARSSL_CIPHER_DES_CBC ); } else #endif /* POLARSSL_DES_C */ return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); if( cipher_info == NULL ) return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); keylen = cipher_info->key_length / 8; if( ( ret = asn1_get_tag( &p, end2, &len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); if( len != cipher_info->iv_size ) return( POLARSSL_ERR_PKCS5_INVALID_FORMAT ); memcpy( iv, p, len ); if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 ) return( ret ); if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 ) return( ret ); if ( ( ret = pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, iterations, keylen, key ) ) != 0 ) { return( ret ); } if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 ) return( ret ); if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 ) return( ret ); if( ( ret = cipher_update( &cipher_ctx, data, datalen, output, &olen ) ) != 0 ) { return( ret ); } if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) return( POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH ); return( 0 ); }
int pkcs11_sign( pkcs11_context *ctx, int mode, md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ) { size_t sig_len = 0, asn_len = 0, oid_size = 0; unsigned char *p = sig; const char *oid; if( NULL == ctx ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); if( RSA_PRIVATE != mode ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); if( md_alg != POLARSSL_MD_NONE ) { const md_info_t *md_info = md_info_from_type( md_alg ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hashlen = md_get_size( md_info ); asn_len = 10 + oid_size; } sig_len = ctx->len; if( hashlen > sig_len || asn_len > sig_len || hashlen + asn_len > sig_len ) { return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } if( md_alg != POLARSSL_MD_NONE ) { /* * DigestInfo ::= SEQUENCE { * digestAlgorithm DigestAlgorithmIdentifier, * digest Digest } * * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * * Digest ::= OCTET STRING */ *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; *p++ = (unsigned char) ( 0x04 + oid_size ); *p++ = ASN1_OID; *p++ = oid_size & 0xFF; memcpy( p, oid, oid_size ); p += oid_size; *p++ = ASN1_NULL; *p++ = 0x00; *p++ = ASN1_OCTET_STRING; *p++ = hashlen; } memcpy( p, hash, hashlen ); if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, asn_len + hashlen, sig, &sig_len ) != CKR_OK ) { return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } return( 0 ); }
/* * Do an RSA operation to sign the message digest */ int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ) { size_t nb_pad, olen, oid_size = 0; unsigned char *p = sig; const char *oid; if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); olen = ctx->len; nb_pad = olen - 3; if( md_alg != POLARSSL_MD_NONE ) { const md_info_t *md_info = md_info_from_type( md_alg ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); nb_pad -= 10 + oid_size; hashlen = md_get_size( md_info ); } nb_pad -= hashlen; if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); *p++ = 0; *p++ = RSA_SIGN; memset( p, 0xFF, nb_pad ); p += nb_pad; *p++ = 0; if( md_alg == POLARSSL_MD_NONE ) { memcpy( p, hash, hashlen ); } else { /* * DigestInfo ::= SEQUENCE { * digestAlgorithm DigestAlgorithmIdentifier, * digest Digest } * * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * * Digest ::= OCTET STRING */ *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; *p++ = (unsigned char) ( 0x04 + oid_size ); *p++ = ASN1_OID; *p++ = oid_size & 0xFF; memcpy( p, oid, oid_size ); p += oid_size; *p++ = ASN1_NULL; *p++ = 0x00; *p++ = ASN1_OCTET_STRING; *p++ = hashlen; memcpy( p, hash, hashlen ); } return( ( mode == RSA_PUBLIC ) ? rsa_public( ctx, sig, sig ) : rsa_private( ctx, f_rng, p_rng, sig, sig ) ); }
/* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function */ int rsa_rsassa_pss_sign( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, int hash_id, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ) { size_t olen; unsigned char *p = sig; unsigned char salt[POLARSSL_MD_MAX_SIZE]; unsigned int slen, hlen, offset = 0; int ret; size_t msb; const md_info_t *md_info; md_context_t md_ctx; if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); olen = ctx->len; switch( hash_id ) { case SIG_RSA_MD2: case SIG_RSA_MD4: case SIG_RSA_MD5: hashlen = 16; break; case SIG_RSA_SHA1: hashlen = 20; break; case SIG_RSA_SHA224: hashlen = 28; break; case SIG_RSA_SHA256: hashlen = 32; break; case SIG_RSA_SHA384: hashlen = 48; break; case SIG_RSA_SHA512: hashlen = 64; break; default: return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } md_info = md_info_from_type( ctx->hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hlen = md_get_size( md_info ); slen = hlen; if( olen < hlen + slen + 2 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); memset( sig, 0, olen ); msb = mpi_msb( &ctx->N ) - 1; // Generate salt of length slen // if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); // Note: EMSA-PSS encoding is over the length of N - 1 bits // msb = mpi_msb( &ctx->N ) - 1; p += olen - hlen * 2 - 2; *p++ = 0x01; memcpy( p, salt, slen ); p += slen; md_init_ctx( &md_ctx, md_info ); // Generate H = Hash( M' ) // md_starts( &md_ctx ); md_update( &md_ctx, p, 8 ); md_update( &md_ctx, hash, hashlen ); md_update( &md_ctx, salt, slen ); md_finish( &md_ctx, p ); // Compensate for boundary condition when applying mask // if( msb % 8 == 0 ) offset = 1; // maskedDB: Apply dbMask to DB // mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); md_free_ctx( &md_ctx ); msb = mpi_msb( &ctx->N ) - 1; sig[0] &= 0xFF >> ( olen * 8 - msb ); p += hlen; *p++ = 0xBC; return( ( mode == RSA_PUBLIC ) ? rsa_public( ctx, sig, sig ) : rsa_private( ctx, sig, sig ) ); }
static int x509_crt_verify_child( x509_crt *child, x509_crt *parent, x509_crt *trust_ca, x509_crl *ca_crl, int path_cnt, int *flags, int (*f_vrfy)(void *, x509_crt *, int, int *), void *p_vrfy ) { int ret; int parent_flags = 0; unsigned char hash[POLARSSL_MD_MAX_SIZE]; x509_crt *grandparent; const md_info_t *md_info; if( x509_time_expired( &child->valid_to ) ) *flags |= BADCERT_EXPIRED; md_info = md_info_from_type( child->sig_md ); if( md_info == NULL ) { /* * Cannot check 'unknown' hash */ *flags |= BADCERT_NOT_TRUSTED; } else { md( md_info, child->tbs.p, child->tbs.len, hash ); if( pk_can_do( &parent->pk, child->sig_pk ) == 0 || pk_verify( &parent->pk, child->sig_md, hash, md_info->size, child->sig.p, child->sig.len ) != 0 ) { *flags |= BADCERT_NOT_TRUSTED; } } #if defined(POLARSSL_X509_CRL_PARSE_C) /* Check trusted CA's CRL for the given crt */ *flags |= x509_crt_verifycrl(child, parent, ca_crl); #endif grandparent = parent->next; while( grandparent != NULL ) { if( grandparent->version == 0 || grandparent->ca_istrue == 0 || parent->issuer_raw.len != grandparent->subject_raw.len || memcmp( parent->issuer_raw.p, grandparent->subject_raw.p, parent->issuer_raw.len ) != 0 ) { grandparent = grandparent->next; continue; } break; } if( grandparent != NULL ) { /* * Part of the chain */ ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } else { ret = x509_crt_verify_top( parent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } /* child is verified to be a child of the parent, call verify callback */ if( NULL != f_vrfy ) if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) return( ret ); *flags |= parent_flags; return( 0 ); }
/* * Add the message padding, then do an RSA operation */ int rsa_pkcs1_encrypt( rsa_context *ctx, int (*f_rng)(void *), void *p_rng, int mode, size_t ilen, const unsigned char *input, unsigned char *output ) { size_t nb_pad, olen; unsigned char *p = output; #if defined(POLARSSL_PKCS1_V21) unsigned int i, hlen; const md_info_t *md_info; md_context_t md_ctx; #endif olen = ctx->len; if( f_rng == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); switch( ctx->padding ) { case RSA_PKCS_V15: if( olen < ilen + 11 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); nb_pad = olen - 3 - ilen; *p++ = 0; *p++ = RSA_CRYPT; while( nb_pad-- > 0 ) { int rng_dl = 100; do { *p = (unsigned char) f_rng( p_rng ); } while( *p == 0 && --rng_dl ); // Check if RNG failed to generate data // if( rng_dl == 0 ) return POLARSSL_ERR_RSA_RNG_FAILED; p++; } *p++ = 0; memcpy( p, input, ilen ); break; #if defined(POLARSSL_PKCS1_V21) case RSA_PKCS_V21: md_info = md_info_from_type( ctx->hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hlen = md_get_size( md_info ); if( olen < ilen + 2 * hlen + 2 || f_rng == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); memset( output, 0, olen ); memset( &md_ctx, 0, sizeof( md_context_t ) ); md_init_ctx( &md_ctx, md_info ); *p++ = 0; // Generate a random octet string seed // for( i = 0; i < hlen; ++i ) *p++ = (unsigned char) f_rng( p_rng ); // Construct DB // md( md_info, p, 0, p ); p += hlen; p += olen - 2 * hlen - 2 - ilen; *p++ = 1; memcpy( p, input, ilen ); // maskedDB: Apply dbMask to DB // mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, &md_ctx ); // maskedSeed: Apply seedMask to seed // mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, &md_ctx ); break; #endif default: return( POLARSSL_ERR_RSA_INVALID_PADDING ); } return( ( mode == RSA_PUBLIC ) ? rsa_public( ctx, output, output ) : rsa_private( ctx, output, output ) ); }
/* * Do an RSA operation, then remove the message padding */ int rsa_pkcs1_decrypt( rsa_context *ctx, int mode, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len) { int ret; size_t ilen; unsigned char *p; unsigned char buf[1024]; #if defined(POLARSSL_PKCS1_V21) unsigned char lhash[POLARSSL_MD_MAX_SIZE]; unsigned int hlen; const md_info_t *md_info; md_context_t md_ctx; #endif ilen = ctx->len; if( ilen < 16 || ilen > (int) sizeof( buf ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); ret = ( mode == RSA_PUBLIC ) ? rsa_public( ctx, input, buf ) : rsa_private( ctx, input, buf ); if( ret != 0 ) return( ret ); p = buf; switch( ctx->padding ) { case RSA_PKCS_V15: if( *p++ != 0 || *p++ != RSA_CRYPT ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); while( *p != 0 ) { if( p >= buf + ilen - 1 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); p++; } p++; break; #if defined(POLARSSL_PKCS1_V21) case RSA_PKCS_V21: if( *p++ != 0 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); md_info = md_info_from_type( ctx->hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hlen = md_get_size( md_info ); memset( &md_ctx, 0, sizeof( md_context_t ) ); md_init_ctx( &md_ctx, md_info ); // Generate lHash // md( md_info, lhash, 0, lhash ); // seed: Apply seedMask to maskedSeed // mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, &md_ctx ); // DB: Apply dbMask to maskedDB // mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, &md_ctx ); p += hlen; // Check validity // if( memcmp( lhash, p, hlen ) != 0 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); p += hlen; while( *p == 0 && p < buf + ilen ) p++; if( p == buf + ilen ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); if( *p++ != 0x01 ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); break; #endif default: return( POLARSSL_ERR_RSA_INVALID_PADDING ); } if (ilen - (int)(p - buf) > output_max_len) return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); *olen = ilen - (int)(p - buf); memcpy( output, p, *olen ); return( 0 ); }
/* * Do an RSA operation to sign the message digest */ int rsa_pkcs1_sign( rsa_context *ctx, int (*f_rng)(void *), void *p_rng, int mode, int hash_id, unsigned int hashlen, const unsigned char *hash, unsigned char *sig ) { size_t nb_pad, olen; unsigned char *p = sig; #if defined(POLARSSL_PKCS1_V21) unsigned char salt[POLARSSL_MD_MAX_SIZE]; unsigned int i, slen, hlen, offset = 0; size_t msb; const md_info_t *md_info; md_context_t md_ctx; #else (void) f_rng; (void) p_rng; #endif olen = ctx->len; switch( ctx->padding ) { case RSA_PKCS_V15: switch( hash_id ) { case SIG_RSA_RAW: nb_pad = olen - 3 - hashlen; break; case SIG_RSA_MD2: case SIG_RSA_MD4: case SIG_RSA_MD5: nb_pad = olen - 3 - 34; break; case SIG_RSA_SHA1: nb_pad = olen - 3 - 35; break; case SIG_RSA_SHA224: nb_pad = olen - 3 - 47; break; case SIG_RSA_SHA256: nb_pad = olen - 3 - 51; break; case SIG_RSA_SHA384: nb_pad = olen - 3 - 67; break; case SIG_RSA_SHA512: nb_pad = olen - 3 - 83; break; default: return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } if( nb_pad < 8 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); *p++ = 0; *p++ = RSA_SIGN; memset( p, 0xFF, nb_pad ); p += nb_pad; *p++ = 0; switch( hash_id ) { case SIG_RSA_RAW: memcpy( p, hash, hashlen ); break; case SIG_RSA_MD2: memcpy( p, ASN1_HASH_MDX, 18 ); memcpy( p + 18, hash, 16 ); p[13] = 2; break; case SIG_RSA_MD4: memcpy( p, ASN1_HASH_MDX, 18 ); memcpy( p + 18, hash, 16 ); p[13] = 4; break; case SIG_RSA_MD5: memcpy( p, ASN1_HASH_MDX, 18 ); memcpy( p + 18, hash, 16 ); p[13] = 5; break; case SIG_RSA_SHA1: memcpy( p, ASN1_HASH_SHA1, 15 ); memcpy( p + 15, hash, 20 ); break; case SIG_RSA_SHA224: memcpy( p, ASN1_HASH_SHA2X, 19 ); memcpy( p + 19, hash, 28 ); p[1] += 28; p[14] = 4; p[18] += 28; break; case SIG_RSA_SHA256: memcpy( p, ASN1_HASH_SHA2X, 19 ); memcpy( p + 19, hash, 32 ); p[1] += 32; p[14] = 1; p[18] += 32; break; case SIG_RSA_SHA384: memcpy( p, ASN1_HASH_SHA2X, 19 ); memcpy( p + 19, hash, 48 ); p[1] += 48; p[14] = 2; p[18] += 48; break; case SIG_RSA_SHA512: memcpy( p, ASN1_HASH_SHA2X, 19 ); memcpy( p + 19, hash, 64 ); p[1] += 64; p[14] = 3; p[18] += 64; break; default: return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } break; #if defined(POLARSSL_PKCS1_V21) case RSA_PKCS_V21: if( f_rng == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); switch( hash_id ) { case SIG_RSA_MD2: case SIG_RSA_MD4: case SIG_RSA_MD5: hashlen = 16; break; case SIG_RSA_SHA1: hashlen = 20; break; case SIG_RSA_SHA224: hashlen = 28; break; case SIG_RSA_SHA256: hashlen = 32; break; case SIG_RSA_SHA384: hashlen = 48; break; case SIG_RSA_SHA512: hashlen = 64; break; default: return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); } md_info = md_info_from_type( ctx->hash_id ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hlen = md_get_size( md_info ); slen = hlen; memset( sig, 0, olen ); memset( &md_ctx, 0, sizeof( md_context_t ) ); md_init_ctx( &md_ctx, md_info ); msb = mpi_msb( &ctx->N ) - 1; // Generate salt of length slen // for( i = 0; i < slen; ++i ) salt[i] = (unsigned char) f_rng( p_rng ); // Note: EMSA-PSS encoding is over the length of N - 1 bits // msb = mpi_msb( &ctx->N ) - 1; p += olen - hlen * 2 - 2; *p++ = 0x01; memcpy( p, salt, slen ); p += slen; // Generate H = Hash( M' ) // md_starts( &md_ctx ); md_update( &md_ctx, p, 8 ); md_update( &md_ctx, hash, hashlen ); md_update( &md_ctx, salt, slen ); md_finish( &md_ctx, p ); // Compensate for boundary condition when applying mask // if( msb % 8 == 0 ) offset = 1; // maskedDB: Apply dbMask to DB // mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); msb = mpi_msb( &ctx->N ) - 1; sig[0] &= 0xFF >> ( olen * 8 - msb ); p += hlen; *p++ = 0xBC; break; #endif default: return( POLARSSL_ERR_RSA_INVALID_PADDING ); } return( ( mode == RSA_PUBLIC ) ? rsa_public( ctx, sig, sig ) : rsa_private( ctx, sig, sig ) ); }
int main( int argc, char *argv[] ) { int ret, i; const md_info_t *md_info; md_context_t md_ctx; md_init( &md_ctx ); if( argc == 1 ) { const int *list; printf( "print mode: generic_sum <md> <file> <file> ...\n" ); printf( "check mode: generic_sum <md> -c <checksum file>\n" ); printf( "\nAvailable message digests:\n" ); list = md_list(); while( *list ) { md_info = md_info_from_type( *list ); printf( " %s\n", md_info->name ); list++; } #if defined(_WIN32) printf( "\n Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( 1 ); } /* * Read the MD from the command line */ md_info = md_info_from_string( argv[1] ); if( md_info == NULL ) { fprintf( stderr, "Message Digest '%s' not found\n", argv[1] ); return( 1 ); } if( md_init_ctx( &md_ctx, md_info) ) { fprintf( stderr, "Failed to initialize context.\n" ); return( 1 ); } ret = 0; if( argc == 4 && strcmp( "-c", argv[2] ) == 0 ) { ret |= generic_check( md_info, argv[3] ); goto exit; } for( i = 2; i < argc; i++ ) ret |= generic_print( md_info, argv[i] ); exit: md_free( &md_ctx ); return( ret ); }
/* * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function */ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig ) { int ret; size_t len, siglen, asn1_len; unsigned char *p, *end; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; md_type_t msg_md_alg; const md_info_t *md_info; asn1_buf oid; if( mode == RSA_PRIVATE && ctx->padding != RSA_PKCS_V15 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); siglen = ctx->len; if( siglen < 16 || siglen > sizeof( buf ) ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); ret = ( mode == RSA_PUBLIC ) ? rsa_public( ctx, sig, buf ) : rsa_private( ctx, f_rng, p_rng, sig, buf ); if( ret != 0 ) return( ret ); p = buf; if( *p++ != 0 || *p++ != RSA_SIGN ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); while( *p != 0 ) { if( p >= buf + siglen - 1 || *p != 0xFF ) return( POLARSSL_ERR_RSA_INVALID_PADDING ); p++; } p++; len = siglen - ( p - buf ); if( len == hashlen && md_alg == POLARSSL_MD_NONE ) { if( memcmp( p, hash, hashlen ) == 0 ) return( 0 ); else return( POLARSSL_ERR_RSA_VERIFY_FAILED ); } md_info = md_info_from_type( md_alg ); if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); hashlen = md_get_size( md_info ); end = p + len; // Parse the ASN.1 structure inside the PKCS#1 v1.5 structure // if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( asn1_len + 2 != len ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( asn1_len + 6 + hashlen != len ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( ( ret = asn1_get_tag( &p, end, &oid.len, ASN1_OID ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); oid.p = p; p += oid.len; if( oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( md_alg != msg_md_alg ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); /* * assume the algorithm parameters must be NULL */ if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_NULL ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( asn1_len != hashlen ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( memcmp( p, hash, hashlen ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); p += hashlen; if( p != end ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); return( 0 ); }