/* Generate an RSA keypair */ int rsa_gen_key(rsa_context *ctx, int nbits, int exponent) { mpi P1, Q1, H, G; int ret; if (ctx->f_rng == NULL || nbits < 128 || exponent < 3) { return EST_ERR_RSA_BAD_INPUT_DATA; } mpi_init(&P1, &Q1, &H, &G, NULL); /* find primes P and Q with Q < P so that: GCD( E, (P-1)*(Q-1) ) == 1 */ MPI_CHK(mpi_lset(&ctx->E, exponent)); do { MPI_CHK(mpi_gen_prime(&ctx->P, (nbits + 1) >> 1, 0, ctx->f_rng, ctx->p_rng)); MPI_CHK(mpi_gen_prime(&ctx->Q, (nbits + 1) >> 1, 0, ctx->f_rng, ctx->p_rng)); if (mpi_cmp_mpi(&ctx->P, &ctx->Q) < 0) { mpi_swap(&ctx->P, &ctx->Q); } if (mpi_cmp_mpi(&ctx->P, &ctx->Q) == 0) { continue; } MPI_CHK(mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q)); if (mpi_msb(&ctx->N) != nbits) { continue; } MPI_CHK(mpi_sub_int(&P1, &ctx->P, 1)); MPI_CHK(mpi_sub_int(&Q1, &ctx->Q, 1)); MPI_CHK(mpi_mul_mpi(&H, &P1, &Q1)); MPI_CHK(mpi_gcd(&G, &ctx->E, &H)); } while (mpi_cmp_int(&G, 1) != 0); /* D = E^-1 mod ((P-1)*(Q-1)) DP = D mod (P - 1) DQ = D mod (Q - 1) QP = Q^-1 mod P */ MPI_CHK(mpi_inv_mod(&ctx->D, &ctx->E, &H)); MPI_CHK(mpi_mod_mpi(&ctx->DP, &ctx->D, &P1)); MPI_CHK(mpi_mod_mpi(&ctx->DQ, &ctx->D, &Q1)); MPI_CHK(mpi_inv_mod(&ctx->QP, &ctx->Q, &ctx->P)); ctx->len = (mpi_msb(&ctx->N) + 7) >> 3; cleanup: mpi_free(&G, &H, &Q1, &P1, NULL); if (ret != 0) { rsa_free(ctx); return EST_ERR_RSA_KEY_GEN_FAILED | ret; } return 0; }
/* Check a public RSA key */ int rsa_check_pubkey(rsa_context *ctx) { if ((ctx->N.p[0] & 1) == 0 || (ctx->E.p[0] & 1) == 0) { return EST_ERR_RSA_KEY_CHECK_FAILED; } if (mpi_msb(&ctx->N) < 128 || mpi_msb(&ctx->N) > 4096) { return EST_ERR_RSA_KEY_CHECK_FAILED; } if (mpi_msb(&ctx->E) < 2 || mpi_msb(&ctx->E) > 64) { return EST_ERR_RSA_KEY_CHECK_FAILED; } return 0; }
void check_key_length (ssl_context *ssl) { uint32_t key_bits; const x509_cert *certificate; const rsa_context *public_key; char buf[1024]; certificate = ssl_get_peer_cert (ssl); if (NULL == certificate) { die ("Getting certificate failed"); } x509parse_dn_gets(buf, 1024, &certificate->subject); verb_debug ("V: Certificate for subject '%s'", buf); public_key = &certificate->rsa; if (NULL == public_key) { die ("public key extraction failure"); } else { verb_debug ("V: public key is ready for inspection"); } key_bits = mpi_msb (&public_key->N); if (MIN_PUB_KEY_LEN >= key_bits) { die ("Unsafe public key size: %d bits", key_bits); } else { verb_debug ("V: key length appears safe"); } }
/* * Check a public RSA key */ int rsa_check_pubkey( rsa_context *ctx ) { if( ( ctx->N.p[0] & 1 ) == 0 || ( ctx->E.p[0] & 1 ) == 0 ) return( XYSSL_ERR_RSA_KEY_CHECK_FAILED ); if( mpi_msb( &ctx->N ) < 128 || mpi_msb( &ctx->N ) > 4096 ) return( XYSSL_ERR_RSA_KEY_CHECK_FAILED ); if( mpi_msb( &ctx->E ) < 2 || mpi_msb( &ctx->E ) > 64 ) return( XYSSL_ERR_RSA_KEY_CHECK_FAILED ); return( 0 ); }
/* * Check a public RSA key */ int rsa_check_pubkey( const rsa_context *ctx ) { if( !ctx->N.p || !ctx->E.p ) return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); if( ( ctx->N.p[0] & 1 ) == 0 || ( ctx->E.p[0] & 1 ) == 0 ) return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); if( mpi_msb( &ctx->N ) < 128 || mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS ) return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); if( mpi_msb( &ctx->E ) < 2 || mpi_msb( &ctx->E ) > 64 ) return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); return( 0 ); }
static int Btohex(lua_State *L) { mpi *a=Bget(L,1); int n = mpi_msb(a); size_t numChars = 3 + n/4; char *s = (char *) malloc(numChars); /*for radix 16, we are safe with one char for every 4 bits with one extra for the terminating 0*/ mpi_write_string(a, 16, s, &numChars); lua_pushstring(L,s); free(s); return 1; }
int chiffrer_rsa(char* data, char* sortie, int taille_data ) { FILE *f; int ret; size_t i; rsa_context rsa; entropy_context entropy; ctr_drbg_context ctr_drbg; char *pers = "rsa_encrypt"; printf( "[i] Seeding the random number generator\n" ); entropy_init( &entropy ); if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy, (unsigned char *) pers, strlen( pers ) ) ) != 0 ) { printf( "[-] ctr_drbg_init returned %d\n", ret ); goto exit; } printf( "[i] Reading private key\n" ); rsa_init( &rsa, RSA_PKCS_V15, 0 ); if( ( ret = mpi_read_string( &rsa.N, RSA_N_BASE, RSA_N ) ) != 0 || ( ret = mpi_read_string( &rsa.D, RSA_D_BASE, RSA_D ) ) != 0 ) { printf( "[-] mpi_read_file returned %d\n", ret ); goto exit; } rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3; /* * Calculate the RSA encryption of the hash. */ printf( "[i] Generating the RSA encrypted value (%d/%d)\n", rsa.len, taille_data ); fflush( stdout ); if( ( ret = rsa_pkcs1_encrypt( &rsa, ctr_drbg_random, &ctr_drbg, RSA_PRIVATE, taille_data, data, sortie ) ) != 0 ) { printf( "[-] rsa_pkcs1_encrypt returned %d\n\n", ret ); goto exit; } printf( "[i] Cryptogramme copie\n"); exit: return( ret ); }
/* * Generate an RSA keypair */ int rsa_gen_key( rsa_context *ctx, int (*f_rng)(void *), void *p_rng, int nbits, int exponent ) { int ret; mpi P1, Q1, H, G; if( f_rng == NULL || nbits < 128 || exponent < 3 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); mpi_init( &P1, &Q1, &H, &G, NULL ); /* * find primes P and Q with Q < P so that: * GCD( E, (P-1)*(Q-1) ) == 1 */ MPI_CHK( mpi_lset( &ctx->E, exponent ) ); do { MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) mpi_swap( &ctx->P, &ctx->Q ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) continue; MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); if( mpi_msb( &ctx->N ) != nbits ) continue; MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); } while( mpi_cmp_int( &G, 1 ) != 0 ); /* * D = E^-1 mod ((P-1)*(Q-1)) * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; cleanup: mpi_free( &G, &H, &Q1, &P1, NULL ); if( ret != 0 ) { rsa_free( ctx ); return( POLARSSL_ERR_RSA_KEY_GEN_FAILED | ret ); } return( 0 ); }
/* * 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 ) ); }
/* * 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 ); }
int sign(unsigned char *output,unsigned char *input, int input_len, char *pri_key_file) { unsigned char * cipher = NULL; unsigned char * k_c = NULL; unsigned char sign[128]; int ret; FILE *fkey; rsa_context rsa_ctx; havege_state prng_ctx; cipher = (unsigned char *)malloc((32)*sizeof(char)); /* ********************** HASH controle integrite *********************** */ k_c = (unsigned char *)malloc(2*KEY_LENGTH*sizeof(unsigned char)); memset(k_c, 0, 2*KEY_LENGTH); //generation de la clef symetrique de KEY_LENGTH bits gen_key(k_c, KEY_LENGTH); sha2_hmac(k_c, KEY_LENGTH, input, input_len, cipher, 0); print_hex(k_c, KEY_LENGTH, "cle secrete utilisée pour le hash : "); /* *** Read the private asymetric key in the file*** */ if( ( fkey = fopen( pri_key_file, "rb" ) ) == NULL ) { ret = 1; printf( " failed\n ! Could not open %s\n" \ " ! Please run rsa_genkey first\n\n",pri_key_file ); goto cleanup; } rsa_init( &rsa_ctx, RSA_PKCS_V15, 0 ); if( ( ret = mpi_read_file( &rsa_ctx.N , 16, fkey ) ) != 0 || ( ret = mpi_read_file( &rsa_ctx.E , 16, fkey ) ) != 0 || ( ret = mpi_read_file( &rsa_ctx.D , 16, fkey ) ) != 0 || ( ret = mpi_read_file( &rsa_ctx.P , 16, fkey ) ) != 0 || ( ret = mpi_read_file( &rsa_ctx.Q , 16, fkey ) ) != 0 || ( ret = mpi_read_file( &rsa_ctx.DP, 16, fkey ) ) != 0 || ( ret = mpi_read_file( &rsa_ctx.DQ, 16, fkey ) ) != 0 || ( ret = mpi_read_file( &rsa_ctx.QP, 16, fkey ) ) != 0 ) { printf( " failed\n ! mpi_read_file returned %d\n\n", ret ); goto cleanup; } rsa_ctx.len = ( mpi_msb( &rsa_ctx.N ) + 7 ) >> 3; fclose( fkey ); /* *** SYM_K(key) : chiffrement RSA de la clé de chiffrement key (16) => rsa-1024 bits = 128 octets en sortie *** */ /* *** cipher = ASYM_Kpriv (Hash) *** */ havege_init(&prng_ctx); memset(sign, 0, 128); if( ( ret = rsa_pkcs1_encrypt( &rsa_ctx, havege_random, &prng_ctx, RSA_PRIVATE, KEY_LENGTH, cipher, sign ) ) != 0 ) { printf( " failed\n ! rsa_pkcs1_encrypt returned %d\n\n", ret ); goto cleanup; } print_hex(sign, sizeof(sign), "Hash chiffrée avec RSA : "); /* *** ASYM_Kpub (K) *** */ output = (unsigned char *) malloc( 128 * sizeof(unsigned char)); memcpy(output, sign, 128); cleanup: if(cipher != NULL) { memset(cipher, 0, 32); free(cipher); } if(k_c != NULL) { memset(k_c, 0, 2*KEY_LENGTH); free(k_c); } memset(&prng_ctx,0x00, sizeof(havege_state)); memset(&rsa_ctx, 0x00, sizeof(rsa_ctx)); memset(sign, 0, 128); return ret; }
int decipher_buffer(unsigned char **output, int *output_len, unsigned char *input, int input_len, char *priv_key_file) { int offset, ret; size_t key_len; unsigned char s_key[32] = {0}; aes_context aes_ctx; rsa_context rsa_ctx; FILE *f; unsigned char iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* *** Init *** */ ret = 1; offset = 0; key_len = 0; f = NULL; /* *** Get private key *** */ f = fopen(priv_key_file, "rb"); if (f == NULL) { fprintf(stderr, "error : unable to open %s\n", priv_key_file); ret = 1; goto cleanup; } rsa_init(&rsa_ctx, RSA_PKCS_V15, 0 ); if (mpi_read_file(&rsa_ctx.N, 16, f) != 0 || mpi_read_file(&rsa_ctx.E, 16, f) != 0 || mpi_read_file(&rsa_ctx.D, 16, f) != 0 || mpi_read_file(&rsa_ctx.P, 16, f) != 0 || mpi_read_file(&rsa_ctx.Q, 16, f) != 0 || mpi_read_file(&rsa_ctx.DP, 16, f) != 0 || mpi_read_file(&rsa_ctx.DQ, 16, f) != 0 || mpi_read_file(&rsa_ctx.QP, 16, f) != 0) { fprintf(stderr, "error : unable to read private key\n"); ret = 1; goto cleanup; } rsa_ctx.len = (mpi_msb(&rsa_ctx.N ) + 7 ) >> 3; /* *** Decipher *** */ ret = rsa_pkcs1_decrypt(&rsa_ctx, RSA_PRIVATE, &key_len, input, s_key, 16); if (ret != 0) { fprintf(stderr, "error : rsa_pkcs1_decrypt failed\n"); ret = 1; goto cleanup; } ret = aes_setkey_dec(&aes_ctx, s_key, 256); if (ret != 0) { fprintf(stderr, "error : aes_setkey_dec failed\n"); ret = 1; goto cleanup; } /* *** Plain text *** */ *output = (unsigned char *) malloc((input_len - 128) * sizeof(unsigned char)); memset(*output, 0, input_len - 128); ret = aes_crypt_cbc(&aes_ctx, AES_DECRYPT, input_len - 128 , iv, input + 128, *output); if (ret != 0) { fprintf(stderr, "error : aes_crypt_cbc failed\n"); ret = 1; goto cleanup; } /* *** Padding *** */ for (offset = input_len - 128 - 1; offset >= 0; offset--) { if((*output)[offset] == 0x80) { *output_len = offset; (*output)[offset] = 0x00; break; } } cleanup: if(f != NULL) fclose(f); rsa_free(&rsa_ctx); return ret; }
/** * Adds padding and encrypts a string using either private or public key. * (depending on mode). * @param message: arbitrary binary string to be encrypted. * @param keytable: table containing either the public or the private key, as generated by gen_key. * @return The cyphertext (as a binary string). * @see rsa_genkey */ static int luarsa_pkcs1_encrypt (lua_State *L) { int res = 0; int mode; size_t lmsg, lresult; rsa_context rsa; char *message = (char*)luaL_checklstring(L, 1, &lmsg); /* message */ char result[KEY_SIZE]; char alt_result[KEY_SIZE]; char* strMode=NULL; if(lua_type(L, 3)==LUA_TSTRING) { printf("Got parameter\n"); strMode = (char*)lua_tostring(L, 3); printf("[%s]\n", strMode); mode = strncmp(strMode, "private", 7) ? RSA_PUBLIC : RSA_PRIVATE; } rsa_init( &rsa, RSA_PKCS_V15, 0, NULL, NULL ); processKey(L, 2, &rsa); /* keytable */ rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3; memset(result, 0, KEY_SIZE); // <test> by Jason printf("\nMode==%s\n", mode==RSA_PUBLIC ? "RSA_PUBLIC" : "RSA_PRIVATE" ); printf("Size==%d\n", lmsg ); printf("Crypt.Size==%d\n", rsa.len ); printf("ver: %d\n", rsa.ver); printf("len: %d\n", rsa.len); printf("padding: %d\n", rsa.padding); printf("hash_id: %d\n", rsa.hash_id); mpi_print("N:%s\n", &rsa.N); mpi_print("E:%s\n", &rsa.E); if(mode!=RSA_PUBLIC) { //mpi_print("D:%s\n", &rsa.D); //mpi_print("P:%s\n", &rsa.P); //mpi_print("Q:%s\n", &rsa.Q); //mpi_print("DP:%s\n", &rsa.DP); //mpi_print("DQ:%s\n", &rsa.DQ); //mpi_print("QP:%s\n", &rsa.QP); //mpi_print("RN:%s\n", &rsa.RN); //mpi_print("RP:%s\n", &rsa.RP); //mpi_print("RQ:%s\n", &rsa.RQ); } // </test> by Jason // pass rsa context and message to encryption engine res = rsa_pkcs1_encrypt(&rsa, RSA_PUBLIC, lmsg, message, result); if(res) luaL_error(L, "Error during cipher (%d)", res); /* lmsg = 128; res = rsa_pkcs1_decrypt(&rsa, mode, &lmsg, result, alt_result); if(res) luaL_error(L, "Error during decipher (%d)", res); printf("(%d)", lmsg); */ push_private_key(L, &rsa); // push encrypted result buffer lua_pushlstring(L, result, rsa.len); /* ciphertext */ rsa_free( &rsa ); return 1; }
static int Bbits(lua_State *L) { mpi *a=Bget(L,1); lua_pushinteger(L, mpi_msb(a)); return 1; }
/* * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. * WARNING: the resulting group should only be used with * pk_group_id_from_specified(), since its base point may not be set correctly * if it was encoded compressed. * * SpecifiedECDomain ::= SEQUENCE { * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), * fieldID FieldID {{FieldTypes}}, * curve Curve, * base ECPoint, * order INTEGER, * cofactor INTEGER OPTIONAL, * hash HashAlgorithm OPTIONAL, * ... * } * * We only support prime-field as field type, and ignore hash and cofactor. */ static int pk_group_from_specified( const asn1_buf *params, ecp_group *grp ) { int ret; unsigned char *p = params->p; const unsigned char * const end = params->p + params->len; const unsigned char *end_field, *end_curve; size_t len; int ver; /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ if( ( ret = asn1_get_int( &p, end, &ver ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( ver < 1 || ver > 3 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); /* * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field * fieldType FIELD-ID.&id({IOSet}), * parameters FIELD-ID.&Type({IOSet}{@fieldType}) * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ret ); end_field = p + len; /* * FIELD-ID ::= TYPE-IDENTIFIER * FieldTypes FIELD-ID ::= { * { Prime-p IDENTIFIED BY prime-field } | * { Characteristic-two IDENTIFIED BY characteristic-two-field } * } * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } */ if( ( ret = asn1_get_tag( &p, end_field, &len, ASN1_OID ) ) != 0 ) return( ret ); if( len != OID_SIZE( OID_ANSI_X9_62_PRIME_FIELD ) || memcmp( p, OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) { return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); } p += len; /* Prime-p ::= INTEGER -- Field of size p. */ if( ( ret = asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); grp->pbits = mpi_msb( &grp->P ); if( p != end_field ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); /* * Curve ::= SEQUENCE { * a FieldElement, * b FieldElement, * seed BIT STRING OPTIONAL * -- Shall be present if used in SpecifiedECDomain * -- with version equal to ecdpVer2 or ecdpVer3 * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ret ); end_curve = p + len; /* * FieldElement ::= OCTET STRING * containing an integer in the case of a prime field */ if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 || ( ret = mpi_read_binary( &grp->A, p, len ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } p += len; if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 || ( ret = mpi_read_binary( &grp->B, p, len ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } p += len; /* Ignore seed BIT STRING OPTIONAL */ if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_BIT_STRING ) ) == 0 ) p += len; if( p != end_curve ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); /* * ECPoint ::= OCTET STRING */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( ( ret = ecp_point_read_binary( grp, &grp->G, ( const unsigned char *) p, len ) ) != 0 ) { /* * If we can't read the point because it's compressed, cheat by * reading only the X coordinate and the parity bit of Y. */ if( ret != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE || ( p[0] != 0x02 && p[0] != 0x03 ) || len != mpi_size( &grp->P ) + 1 || mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || mpi_lset( &grp->G.Z, 1 ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); } } p += len; /* * order INTEGER */ if( ( ret = asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); grp->nbits = mpi_msb( &grp->N ); /* * Allow optional elements by purposefully not enforcing p == end here. */ return( 0 ); }
int main( int argc, char *argv[] ) { FILE *f; int ret, i; rsa_context rsa; unsigned char hash[20]; unsigned char buf[512]; ret = 1; if( argc != 2 ) { printf( "usage: rsa_sign <filename>\n" ); #ifdef WIN32 printf( "\n" ); #endif goto exit; } printf( "\n . Reading private key from rsa_priv.txt" ); fflush( stdout ); if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL ) { ret = 1; printf( " failed\n ! Could not open rsa_priv.txt\n" \ " ! Please run rsa_genkey first\n\n" ); goto exit; } rsa_init( &rsa, RSA_PKCS_V15, 0, NULL, NULL ); if( ( ret = mpi_read_file( &rsa.N , 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.E , 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.D , 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.P , 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.Q , 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.DP, 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.DQ, 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.QP, 16, f ) ) != 0 ) { printf( " failed\n ! mpi_read_file returned %d\n\n", ret ); goto exit; } rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3; fclose( f ); /* * Compute the SHA-1 hash of the input file, * then calculate the RSA signature of the hash. */ printf( "\n . Generating the RSA/SHA-1 signature" ); fflush( stdout ); if( ( ret = sha1_file( argv[1], hash ) ) != 0 ) { printf( " failed\n ! Could not open or read %s\n\n", argv[1] ); goto exit; } if( ( ret = rsa_pkcs1_sign( &rsa, RSA_PRIVATE, SIG_RSA_SHA1, 20, hash, buf ) ) != 0 ) { printf( " failed\n ! rsa_pkcs1_sign returned %d\n\n", ret ); goto exit; } /* * Write the signature into <filename>-sig.txt */ memcpy( argv[1] + strlen( argv[1] ), ".sig", 5 ); if( ( f = fopen( argv[1], "wb+" ) ) == NULL ) { ret = 1; printf( " failed\n ! Could not create %s\n\n", argv[1] ); goto exit; } for( i = 0; i < rsa.len; i++ ) fprintf( f, "%02X%s", buf[i], ( i + 1 ) % 16 == 0 ? "\r\n" : " " ); fclose( f ); printf( "\n . Done (created \"%s\")\n\n", argv[1] ); exit: #ifdef WIN32 printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( int argc, char *argv[] ) { FILE *f; int ret, c; size_t i; rsa_context rsa; entropy_context entropy; ctr_drbg_context ctr_drbg; unsigned char result[1024]; unsigned char buf[512]; const char *pers = "rsa_decrypt"; ((void) argv); memset(result, 0, sizeof( result ) ); ret = 1; if( argc != 1 ) { polarssl_printf( "usage: rsa_decrypt\n" ); #if defined(_WIN32) polarssl_printf( "\n" ); #endif goto exit; } polarssl_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); entropy_init( &entropy ); if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { polarssl_printf( " failed\n ! ctr_drbg_init returned %d\n", ret ); goto exit; } polarssl_printf( "\n . Reading private key from rsa_priv.txt" ); fflush( stdout ); if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL ) { polarssl_printf( " failed\n ! Could not open rsa_priv.txt\n" \ " ! Please run rsa_genkey first\n\n" ); goto exit; } rsa_init( &rsa, RSA_PKCS_V15, 0 ); if( ( ret = mpi_read_file( &rsa.N , 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.E , 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.D , 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.P , 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.Q , 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.DP, 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.DQ, 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.QP, 16, f ) ) != 0 ) { polarssl_printf( " failed\n ! mpi_read_file returned %d\n\n", ret ); goto exit; } rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3; fclose( f ); /* * Extract the RSA encrypted value from the text file */ ret = 1; if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL ) { polarssl_printf( "\n ! Could not open %s\n\n", "result-enc.txt" ); goto exit; } i = 0; while( fscanf( f, "%02X", &c ) > 0 && i < (int) sizeof( buf ) ) buf[i++] = (unsigned char) c; fclose( f ); if( i != rsa.len ) { polarssl_printf( "\n ! Invalid RSA signature format\n\n" ); goto exit; } /* * Decrypt the encrypted RSA data and print the result. */ polarssl_printf( "\n . Decrypting the encrypted data" ); fflush( stdout ); if( ( ret = rsa_pkcs1_decrypt( &rsa, ctr_drbg_random, &ctr_drbg, RSA_PRIVATE, &i, buf, result, 1024 ) ) != 0 ) { polarssl_printf( " failed\n ! rsa_pkcs1_decrypt returned %d\n\n", ret ); goto exit; } polarssl_printf( "\n . OK\n\n" ); polarssl_printf( "The decrypted result is: '%s'\n\n", result ); ret = 0; exit: ctr_drbg_free( &ctr_drbg ); entropy_free( &entropy ); #if defined(_WIN32) polarssl_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( int argc, char *argv[] ) { FILE *f; int ret, i, c; rsa_context rsa; unsigned char hash[20]; unsigned char buf[512]; ret = 1; if( argc != 2 ) { printf( "usage: rsa_verify <filename>\n" ); #ifdef WIN32 printf( "\n" ); #endif goto exit; } printf( "\n . Reading public key from rsa_pub.txt" ); fflush( stdout ); if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL ) { printf( " failed\n ! Could not open rsa_pub.txt\n" \ " ! Please run rsa_genkey first\n\n" ); goto exit; } rsa_init( &rsa, RSA_PKCS_V15, 0, NULL, NULL ); if( ( ret = mpi_read_file( &rsa.N, 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.E, 16, f ) ) != 0 ) { printf( " failed\n ! mpi_read_file returned %d\n\n", ret ); goto exit; } rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3; fclose( f ); /* * Extract the RSA signature from the text file */ ret = 1; i = strlen( argv[1] ); memcpy( argv[1] + i, ".sig", 5 ); if( ( f = fopen( argv[1], "rb" ) ) == NULL ) { printf( "\n ! Could not open %s\n\n", argv[1] ); goto exit; } argv[1][i] = '\0', i = 0; while( fscanf( f, "%02X", &c ) > 0 && i < (int) sizeof( buf ) ) buf[i++] = (unsigned char) c; fclose( f ); if( i != rsa.len ) { printf( "\n ! Invalid RSA signature format\n\n" ); goto exit; } /* * Compute the SHA-1 hash of the input file and compare * it with the hash decrypted from the RSA signature. */ printf( "\n . Verifying the RSA/SHA-1 signature" ); fflush( stdout ); if( ( ret = sha1_file( argv[1], hash ) ) != 0 ) { printf( " failed\n ! Could not open or read %s\n\n", argv[1] ); goto exit; } if( ( ret = rsa_pkcs1_verify( &rsa, RSA_PUBLIC, RSA_SHA1, 20, hash, buf ) ) != 0 ) { printf( " failed\n ! rsa_pkcs1_verify returned %d\n\n", ret ); goto exit; } printf( "\n . OK (the decrypted SHA-1 hash matches)\n\n" ); ret = 0; exit: #ifdef WIN32 printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* * 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 main( int argc, char *argv[] ) { FILE *f; int ret; size_t n, buflen; int server_fd = -1; unsigned char *p, *end; unsigned char buf[2048]; unsigned char hash[20]; const char *pers = "dh_client"; entropy_context entropy; ctr_drbg_context ctr_drbg; rsa_context rsa; dhm_context dhm; aes_context aes; ((void) argc); ((void) argv); memset( &rsa, 0, sizeof( rsa ) ); memset( &dhm, 0, sizeof( dhm ) ); /* * 1. Setup the RNG */ printf( "\n . Seeding the random number generator" ); fflush( stdout ); entropy_init( &entropy ); if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { printf( " failed\n ! ctr_drbg_init returned %d\n", ret ); goto exit; } /* * 2. Read the server's public RSA key */ printf( "\n . Reading public key from rsa_pub.txt" ); fflush( stdout ); if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL ) { ret = 1; printf( " failed\n ! Could not open rsa_pub.txt\n" \ " ! Please run rsa_genkey first\n\n" ); goto exit; } rsa_init( &rsa, RSA_PKCS_V15, 0 ); if( ( ret = mpi_read_file( &rsa.N, 16, f ) ) != 0 || ( ret = mpi_read_file( &rsa.E, 16, f ) ) != 0 ) { printf( " failed\n ! mpi_read_file returned %d\n\n", ret ); goto exit; } rsa.len = ( mpi_msb( &rsa.N ) + 7 ) >> 3; fclose( f ); /* * 3. Initiate the connection */ printf( "\n . Connecting to tcp/%s/%d", SERVER_NAME, SERVER_PORT ); fflush( stdout ); if( ( ret = net_connect( &server_fd, SERVER_NAME, SERVER_PORT ) ) != 0 ) { printf( " failed\n ! net_connect returned %d\n\n", ret ); goto exit; } /* * 4a. First get the buffer length */ printf( "\n . Receiving the server's DH parameters" ); fflush( stdout ); memset( buf, 0, sizeof( buf ) ); if( ( ret = net_recv( &server_fd, buf, 2 ) ) != 2 ) { printf( " failed\n ! net_recv returned %d\n\n", ret ); goto exit; } n = buflen = ( buf[0] << 8 ) | buf[1]; if( buflen < 1 || buflen > sizeof( buf ) ) { printf( " failed\n ! Got an invalid buffer length\n\n" ); goto exit; } /* * 4b. Get the DHM parameters: P, G and Ys = G^Xs mod P */ memset( buf, 0, sizeof( buf ) ); if( ( ret = net_recv( &server_fd, buf, n ) ) != (int) n ) { printf( " failed\n ! net_recv returned %d\n\n", ret ); goto exit; } p = buf, end = buf + buflen; if( ( ret = dhm_read_params( &dhm, &p, end ) ) != 0 ) { printf( " failed\n ! dhm_read_params returned %d\n\n", ret ); goto exit; } if( dhm.len < 64 || dhm.len > 512 ) { ret = 1; printf( " failed\n ! Invalid DHM modulus size\n\n" ); goto exit; } /* * 5. Check that the server's RSA signature matches * the SHA-1 hash of (P,G,Ys) */ printf( "\n . Verifying the server's RSA signature" ); fflush( stdout ); p += 2; if( ( n = (size_t) ( end - p ) ) != rsa.len ) { ret = 1; printf( " failed\n ! Invalid RSA signature size\n\n" ); goto exit; } sha1( buf, (int)( p - 2 - buf ), hash ); if( ( ret = rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 0, hash, p ) ) != 0 ) { printf( " failed\n ! rsa_pkcs1_verify returned %d\n\n", ret ); goto exit; } /* * 6. Send our public value: Yc = G ^ Xc mod P */ printf( "\n . Sending own public value to server" ); fflush( stdout ); n = dhm.len; if( ( ret = dhm_make_public( &dhm, dhm.len, buf, n, ctr_drbg_random, &ctr_drbg ) ) != 0 ) { printf( " failed\n ! dhm_make_public returned %d\n\n", ret ); goto exit; } if( ( ret = net_send( &server_fd, buf, n ) ) != (int) n ) { printf( " failed\n ! net_send returned %d\n\n", ret ); goto exit; } /* * 7. Derive the shared secret: K = Ys ^ Xc mod P */ printf( "\n . Shared secret: " ); fflush( stdout ); n = dhm.len; if( ( ret = dhm_calc_secret( &dhm, buf, &n ) ) != 0 ) { printf( " failed\n ! dhm_calc_secret returned %d\n\n", ret ); goto exit; } for( n = 0; n < 16; n++ ) printf( "%02x", buf[n] ); /* * 8. Setup the AES-256 decryption key * * This is an overly simplified example; best practice is * to hash the shared secret with a random value to derive * the keying material for the encryption/decryption keys, * IVs and MACs. */ printf( "...\n . Receiving and decrypting the ciphertext" ); fflush( stdout ); aes_setkey_dec( &aes, buf, 256 ); memset( buf, 0, sizeof( buf ) ); if( ( ret = net_recv( &server_fd, buf, 16 ) ) != 16 ) { printf( " failed\n ! net_recv returned %d\n\n", ret ); goto exit; } aes_crypt_ecb( &aes, AES_DECRYPT, buf, buf ); buf[16] = '\0'; printf( "\n . Plaintext is \"%s\"\n\n", (char *) buf ); exit: net_close( server_fd ); rsa_free( &rsa ); dhm_free( &dhm ); #if defined(_WIN32) printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* * 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 ) ); }