result_t PKey::verify(Buffer_base *sign, Buffer_base *data, bool &retVal, exlib::AsyncEvent *ac) { if (switchToAsync(ac)) return CHECK_ERROR(CALL_E_NOSYNC); int ret; std::string str; std::string strsign; data->toString(str); sign->toString(strsign); ret = pk_verify(&m_key, POLARSSL_MD_NONE, (const unsigned char *)str.c_str(), str.length(), (const unsigned char *)strsign.c_str(), strsign.length()); if (ret == POLARSSL_ERR_ECP_VERIFY_FAILED || ret == POLARSSL_ERR_RSA_VERIFY_FAILED) { retVal = false; return 0; } if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); retVal = true; return 0; }
/* * Verify a signature with options */ int pk_verify_ext( pk_type_t type, const void *options, pk_context *ctx, md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ) { if( ctx == NULL || ctx->pk_info == NULL ) return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); if( ! pk_can_do( ctx, type ) ) return( POLARSSL_ERR_PK_TYPE_MISMATCH ); if( type == POLARSSL_PK_RSASSA_PSS ) { #if defined(POLARSSL_RSA_C) && defined(POLARSSL_PKCS1_V21) int ret; const pk_rsassa_pss_options *pss_opts; if( options == NULL ) return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); pss_opts = (const pk_rsassa_pss_options *) options; if( sig_len < pk_get_len( ctx ) ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); ret = rsa_rsassa_pss_verify_ext( pk_rsa( *ctx ), NULL, NULL, RSA_PUBLIC, md_alg, hash_len, hash, pss_opts->mgf1_hash_id, pss_opts->expected_salt_len, sig ); if( ret != 0 ) return( ret ); if( sig_len > pk_get_len( ctx ) ) return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH ); return( 0 ); #else return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); #endif } /* General case: no options */ if( options != NULL ) return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); return( pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); }
int main( int argc, char *argv[] ) { FILE *f; int ret = 1; size_t i; pk_context pk; unsigned char hash[20]; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; char filename[512]; pk_init( &pk ); if( argc != 3 ) { printf( "usage: pk_verify <key_file> <filename>\n" ); #if defined(_WIN32) printf( "\n" ); #endif goto exit; } printf( "\n . Reading public key from '%s'", argv[1] ); fflush( stdout ); if( ( ret = pk_parse_public_keyfile( &pk, argv[1] ) ) != 0 ) { printf( " failed\n ! pk_parse_public_keyfile returned -0x%04x\n", -ret ); goto exit; } /* * Extract the signature from the text file */ ret = 1; snprintf( filename, sizeof(filename), "%s.sig", argv[2] ); if( ( f = fopen( filename, "rb" ) ) == NULL ) { printf( "\n ! Could not open %s\n\n", filename ); goto exit; } i = fread( buf, 1, sizeof(buf), f ); fclose( f ); /* * Compute the SHA-1 hash of the input file and compare * it with the hash decrypted from the signature. */ printf( "\n . Verifying the SHA-1 signature" ); fflush( stdout ); if( ( ret = sha1_file( argv[2], hash ) ) != 0 ) { printf( " failed\n ! Could not open or read %s\n\n", argv[2] ); goto exit; } if( ( ret = pk_verify( &pk, POLARSSL_MD_SHA1, hash, 0, buf, i ) ) != 0 ) { printf( " failed\n ! pk_verify returned -0x%04x\n", -ret ); goto exit; } printf( "\n . OK (the decrypted SHA-1 hash matches)\n\n" ); ret = 0; exit: pk_free( &pk ); #if defined(POLARSSL_ERROR_C) polarssl_strerror( ret, (char *) buf, sizeof(buf) ); printf( " ! Last error was: %s\n", buf ); #endif #if defined(_WIN32) printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
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 ); }
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 ); }
/* * 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; }
void asymmetric_signature_verify(struct item *key, struct item *item, struct item *signature) /*@ requires [?f]world(?pub, ?key_clsfy) &*& item(item, ?i, pub) &*& item(key, ?k, pub) &*& item(signature, ?sig, pub) &*& sig == asymmetric_signature_item(?principal1, ?count1, ?pay1, ?ent) &*& k == public_key_item(?principal2, ?count2); @*/ /*@ ensures [f]world(pub, key_clsfy) &*& item(item, i, pub) &*& item(key, k, pub) &*& item(signature, sig, pub) &*& switch(pay1) { case some(pay2): return col || (principal1 == principal2 && count1 == count2 && i == pay2); case none: return true == col; }; @*/ { debug_print("ASYM SIGNATURE CHECKING:\n"); print_item(signature); check_is_asymmetric_signature(signature); { pk_context context; unsigned int olen; char* output; // Key //@ close pk_context(&context); //@ open [f]world(pub, key_clsfy); pk_init(&context); //@ close [f]world(pub, key_clsfy); set_public_key(&context, key); /*@ assert pk_context_with_key(&context, pk_public, ?principal3, ?count3, RSA_BIT_KEY_SIZE); @*/ // Signature checking //@ open item(item, ?i_old, pub); //@ assert item->content |-> ?i_cont &*& item->size |-> ?i_size; //@ assert crypto_chars(secret, i_cont, i_size, ?i_cs); //@ assert [_]item_constraints(i, i_cs, pub); //@ open item(signature, _, pub); //@ assert signature->content |-> ?s_cont &*& signature->size |-> ?s_size; //@ assert crypto_chars(secret, s_cont, s_size, ?sig_cs); //@ open [_]item_constraints(sig, sig_cs, pub); //@ open ic_parts(sig)(?sig_tag, ?sig_cont); //@ take_append(TAG_LENGTH, sig_tag, sig_cont); //@ drop_append(TAG_LENGTH, sig_tag, sig_cont); //@ open [_]ic_cg(sig)(_, ?cg_sig); //@ assert cg_sig == cg_asym_signature(principal1, count1, ?cs_pay, ent); if (item->size > RSA_KEY_SIZE) abort_crypto_lib("Assymetric signature checking failed: incorrect sizes"); //@ crypto_chars_limits(s_cont); //@ crypto_chars_split(s_cont, TAG_LENGTH); //@ assert crypto_chars(secret, s_cont, TAG_LENGTH, sig_tag); //@ assert crypto_chars(secret, s_cont + TAG_LENGTH, ?s, sig_cont); //@ assert s == s_size - TAG_LENGTH; //@ if (col) cg_sig = chars_for_cg_sur(sig_cont, tag_asym_signature); //@ if (col) crypto_chars_to_chars(s_cont + TAG_LENGTH, s); //@ if (col) public_chars_extract(s_cont + TAG_LENGTH, cg_sig); //@ if (col) chars_to_secret_crypto_chars(s_cont + TAG_LENGTH, s); //@ close cryptogram(s_cont + TAG_LENGTH, s, sig_cont, cg_sig); if(pk_verify(&context, POLARSSL_MD_NONE, item->content, (unsigned int) item->size, signature->content + TAG_LENGTH, (unsigned int) (signature->size - TAG_LENGTH)) != 0) abort_crypto_lib("Signing check failed: signature" "was not created with the provided key"); //@ pk_release_context_with_key(&context); pk_free(&context); //@ open pk_context(&context); //@ open cryptogram(s_cont + TAG_LENGTH, s, sig_cont, cg_sig); //@ crypto_chars_join(s_cont); //@ close item(signature, sig, pub); /*@ if (!col) { assert principal2 == principal3; assert count2 == count3; assert cs_pay == i_cs; open [_]item_constraints(i, cs_pay, pub); switch(pay1) { case some(pay2): assert [_]item_constraints(pay2, cs_pay, pub); item_constraints_injective(i, pay2, cs_pay); case none: open [_]ill_formed_item_chars(sig)(cs_pay); assert false; } } @*/ //@ close item(item, i, pub); } }