/* * Setup and write the ServerKeyExchange parameters */ int dhm_make_params( dhm_context *ctx, int x_size, unsigned char *output, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret, n; size_t n1, n2, n3; unsigned char *p; /* * Generate X as large as possible ( < P ) */ n = x_size / sizeof( t_uint ) + 1; mpi_fill_random( &ctx->X, n, f_rng, p_rng ); while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) mpi_shift_r( &ctx->X, 1 ); /* * Calculate GX = G^X mod P */ MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, &ctx->P , &ctx->RP ) ); if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) return( ret ); /* * export P, G, GX */ #define DHM_MPI_EXPORT(X,n) \ MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \ *p++ = (unsigned char)( n >> 8 ); \ *p++ = (unsigned char)( n ); p += n; n1 = mpi_size( &ctx->P ); n2 = mpi_size( &ctx->G ); n3 = mpi_size( &ctx->GX ); p = output; DHM_MPI_EXPORT( &ctx->P , n1 ); DHM_MPI_EXPORT( &ctx->G , n2 ); DHM_MPI_EXPORT( &ctx->GX, n3 ); *olen = p - output; ctx->len = n1; cleanup: if( ret != 0 ) return( POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED + ret ); return( 0 ); }
/* * Setup and write the ServerKeyExchange parameters */ int dhm_make_params( dhm_context *ctx, int x_size, unsigned char *output, int *olen, int (*f_rng)(void *), void *p_rng ) { int i, ret, n, n1, n2, n3; unsigned char *p; /* * generate X and calculate GX = G^X mod P */ n = x_size / sizeof( t_int ); MPI_CHK( mpi_grow( &ctx->X, n ) ); MPI_CHK( mpi_lset( &ctx->X, 0 ) ); n = x_size >> 3; p = (unsigned char *) ctx->X.p; for( i = 0; i < n; i++ ) *p++ = (unsigned char) f_rng( p_rng ); while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) mpi_shift_r( &ctx->X, 1 ); MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, &ctx->P , &ctx->RP ) ); /* * export P, G, GX */ #define DHM_MPI_EXPORT(X,n) \ MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \ *p++ = (unsigned char)( n >> 8 ); \ *p++ = (unsigned char)( n ); p += n; n1 = mpi_size( &ctx->P ); n2 = mpi_size( &ctx->G ); n3 = mpi_size( &ctx->GX ); p = output; DHM_MPI_EXPORT( &ctx->P , n1 ); DHM_MPI_EXPORT( &ctx->G , n2 ); DHM_MPI_EXPORT( &ctx->GX, n3 ); *olen = p - output; ctx->len = n1; cleanup: if( ret != 0 ) return( ret | XYSSL_ERR_DHM_MAKE_PARAMS_FAILED ); return( 0 ); }
/* * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER -- e * } */ static int pk_get_rsapubkey( unsigned char **p, const unsigned char *end, rsa_context *rsa ) { int ret; size_t len; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); if( *p + len != end ) return( POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); if( ( ret = asn1_get_mpi( p, end, &rsa->N ) ) != 0 || ( ret = asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret ); if( *p != end ) return( POLARSSL_ERR_PK_INVALID_PUBKEY + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); if( ( ret = rsa_check_pubkey( rsa ) ) != 0 ) return( POLARSSL_ERR_PK_INVALID_PUBKEY ); rsa->len = mpi_size( &rsa->N ); return( 0 ); }
/* * Parse the ServerKeyExchange parameters */ int dhm_read_params( dhm_context *ctx, unsigned char **p, const unsigned char *end ) { int ret, n; memset( ctx, 0, sizeof( dhm_context ) ); if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) return( ret ); if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) return( ret ); ctx->len = mpi_size( &ctx->P ); if( end - *p < 2 ) return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); n = ( (*p)[0] << 8 ) | (*p)[1]; (*p) += 2; if( end != *p + n ) return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); return( 0 ); }
/* * Derive and export the shared secret (G^Y)^X mod P */ int dhm_calc_secret( dhm_context *ctx, unsigned char *output, size_t *olen ) { int ret; if( ctx == NULL || *olen < ctx->len ) return( POLARSSL_ERR_DHM_BAD_INPUT_DATA ); MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X, &ctx->P, &ctx->RP ) ); if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) return( ret ); *olen = mpi_size( &ctx->K ); MPI_CHK( mpi_write_binary( &ctx->K, output, *olen ) ); cleanup: if( ret != 0 ) return( POLARSSL_ERR_DHM_CALC_SECRET_FAILED + ret ); return( 0 ); }
int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ) { int ret; size_t len = 0; // Write the MPI // len = mpi_size( X ); if( *p - start < (int) len ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); (*p) -= len; MPI_CHK( mpi_write_binary( X, *p, len ) ); // DER format assumes 2s complement for numbers, so the leftmost bit // should be 0 for positive numbers and 1 for negative numbers. // if ( X->s ==1 && **p & 0x80 ) { if( *p - start < 1 ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); *--(*p) = 0x00; len += 1; } ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_INTEGER ) ); ret = (int) len; cleanup: return( ret ); }
/* * Check if the public key is valid */ int rsa_check_pubkey( rsa_context *ctx ) { if( ( ctx->N.p[0] & 1 ) == 0 || ( ctx->E.p[0] & 1 ) == 0 ) return( ERR_RSA_KEY_CHK_FAILED ); if( mpi_size( &ctx->N ) < 128 || mpi_size( &ctx->N ) > 4096 ) return( ERR_RSA_KEY_CHK_FAILED ); if( mpi_size( &ctx->E ) < 2 || mpi_size( &ctx->E ) > 64 ) return( ERR_RSA_KEY_CHK_FAILED ); return( 0 ); }
/* * Generate an RSA keypair */ int rsa_gen_key( rsa_context *ctx, int nbits, int exponent, ulong (*rng_fn)(void *), void *rng_st ) { int ret; mpi P1, Q1, H, G; mpi_init( &P1, &Q1, &H, &G, NULL ); memset( ctx, 0, sizeof( rsa_context ) ); /* * find primes P and Q with Q < P so that: * GCD( E, (P-1)*(Q-1) ) == 1 */ CHK( mpi_lset( &ctx->E, exponent ) ); nbits >>= 1; do { CHK( mpi_gen_prime( &ctx->P, nbits, 0, rng_fn, rng_st ) ); CHK( mpi_gen_prime( &ctx->Q, nbits, 0, rng_fn, rng_st ) ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) mpi_swap( &ctx->P, &ctx->Q ); CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); 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 */ CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); ctx->len = ( mpi_size( &ctx->N ) + 7 ) >> 3; cleanup: mpi_free( &P1, &Q1, &H, &G, NULL ); if( ret != 0 ) { rsa_free( ctx ); return( ERR_RSA_KEYGEN_FAILED | ret ); } return( 0 ); }
static int Btotext(lua_State *L) { mpi *a = Bget(L,1); int n = mpi_size(a); unsigned char *s = (unsigned char *) malloc(n); if (s == NULL) return 0; mpi_write_binary(a, s, n); lua_pushlstring(L, (const char *) s, n); free(s); return 1; }
int rsa_parse_public_key( rsa_context *rsa, unsigned char *buf, int buflen ) { unsigned char *p, *end; int ret, len; p = buf; end = buf+buflen; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret ); } if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) == 0 ) { /* Skip over embedded rsaEncryption Object */ p+=len; /* The RSAPublicKey ASN1 container is wrapped in a BIT STRING */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_BIT_STRING ) ) != 0 ) { return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret ); } /* Limit range to that BIT STRING */ end = p + len; p++; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret ); } } if ( ( ( ret = asn1_get_mpi( &p, end, &(rsa->N) ) ) == 0 ) && ( ( ret = asn1_get_mpi( &p, end, &(rsa->E) ) ) == 0 ) ) { rsa->len = mpi_size( &rsa->N ); return 0; } return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret ); }
static mpi_message_t* mpi_message_new(MPI_Datatype type, int stride, int tag) { ASSERT(stride > 0); mpi_message_t* msg = polymec_malloc(sizeof(mpi_message_t)); msg->type = type; msg->stride = stride; msg->tag = tag; msg->data_size = mpi_size(type); msg->num_sends = 0; msg->num_receives = 0; msg->num_requests = 0; msg->requests = NULL; msg->send_buffers = NULL; msg->send_buffer_sizes = NULL; msg->dest_procs = NULL; msg->receive_buffers = NULL; msg->receive_buffer_sizes = NULL; msg->source_procs = NULL; return msg; }
/* * Derive and export the shared secret */ int ecdh_calc_secret( ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; if( ctx == NULL ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); if( ( ret = ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng ) ) != 0 ) { return( ret ); } if( mpi_size( &ctx->z ) > blen ) return( POLARSSL_ERR_ECP_BAD_INPUT_DATA ); *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); return mpi_write_binary( &ctx->z, buf, *olen ); }
/* * Parse a private RSA key */ int rsa_parse_key( rsa_context *rsa, unsigned char *buf, int buflen, unsigned char *pwd, int pwdlen ) { int ret, len, enc; unsigned char *s1, *s2; unsigned char *p, *end; s1 = (unsigned char *) strstr( (char *) buf, "-----BEGIN RSA PRIVATE KEY-----" ); if( s1 != NULL ) { s2 = (unsigned char *) strstr( (char *) buf, "-----END RSA PRIVATE KEY-----" ); if( s2 == NULL || s2 <= s1 ) return( POLARSSL_ERR_X509_KEY_INVALID_PEM ); s1 += 31; if( *s1 == '\r' ) s1++; if( *s1 == '\n' ) s1++; else return( POLARSSL_ERR_X509_KEY_INVALID_PEM ); enc = 0; if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) { return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); } len = 0; ret = base64_decode( NULL, &len, s1, s2 - s1 ); if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER ) return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM ); if( ( buf = (unsigned char *) malloc( len ) ) == NULL ) return( 1 ); if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 ) { free( buf ); return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM ); } buflen = len; if( enc != 0 ) { return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); } } memset( rsa, 0, sizeof( rsa_context ) ); p = buf; end = buf + buflen; /* * RSAPrivateKey ::= SEQUENCE { * version Version, * modulus INTEGER, -- n * publicExponent INTEGER, -- e * privateExponent INTEGER, -- d * prime1 INTEGER, -- p * prime2 INTEGER, -- q * exponent1 INTEGER, -- d mod (p-1) * exponent2 INTEGER, -- d mod (q-1) * coefficient INTEGER, -- (inverse of q) mod p * otherPrimeInfos OtherPrimeInfos OPTIONAL * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { if( s1 != NULL ) free( buf ); rsa_free( rsa ); return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret ); } end = p + len; if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) { if( s1 != NULL ) free( buf ); rsa_free( rsa ); return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret ); } if( rsa->ver != 0 ) { if( s1 != NULL ) free( buf ); rsa_free( rsa ); return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION ); } if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) { if( s1 != NULL ) free( buf ); rsa_free( rsa ); return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT ); } rsa->len = mpi_size( &rsa->N ); if( p != end ) { if( s1 != NULL ) free( buf ); rsa_free( rsa ); return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } if( ( ret = rsa_check_privkey( rsa ) ) != 0 ) { if( s1 != NULL ) free( buf ); rsa_free( rsa ); return( ret ); } if( s1 != NULL ) free( buf ); return( 0 ); }
void all2all(const std::vector<T>& send_data, std::vector<T>& recv_data) { #ifdef HAS_MPI // Get the mpi rank and size size_t mpi_size(size()); ASSERT_EQ(send_data.size(), mpi_size); if(recv_data.size() != mpi_size) recv_data.resize(mpi_size); // Serialize the output data and compute buffer sizes graphlab::charstream cstrm(128); graphlab::oarchive oarc(cstrm); std::vector<int> send_buffer_sizes(mpi_size); for(size_t i = 0; i < mpi_size; ++i) { const size_t OLD_SIZE(cstrm->size()); oarc << send_data[i]; cstrm.flush(); const size_t ELEM_SIZE(cstrm->size() - OLD_SIZE); send_buffer_sizes[i] = ELEM_SIZE; } cstrm.flush(); char* send_buffer = cstrm->c_str(); std::vector<int> send_offsets(send_buffer_sizes); int total_send = 0; for(size_t i = 0; i < send_offsets.size(); ++i) { const int tmp = send_offsets[i]; send_offsets[i] = total_send; total_send += tmp; } // AlltoAll scatter the buffer sizes std::vector<int> recv_buffer_sizes(mpi_size); int error = MPI_Alltoall(&(send_buffer_sizes[0]), 1, MPI_INT, &(recv_buffer_sizes[0]), 1, MPI_INT, MPI_COMM_WORLD); ASSERT_EQ(error, MPI_SUCCESS); // Construct offsets std::vector<int> recv_offsets(recv_buffer_sizes); int total_recv = 0; for(size_t i = 0; i < recv_offsets.size(); ++i){ const int tmp = recv_offsets[i]; recv_offsets[i] = total_recv; total_recv += tmp; } // Do the massive send std::vector<char> recv_buffer(total_recv); error = MPI_Alltoallv(send_buffer, &(send_buffer_sizes[0]), &(send_offsets[0]), MPI_BYTE, &(recv_buffer[0]), &(recv_buffer_sizes[0]), &(recv_offsets[0]), MPI_BYTE, MPI_COMM_WORLD); ASSERT_EQ(error, MPI_SUCCESS); // Deserialize the result namespace bio = boost::iostreams; typedef bio::stream<bio::array_source> icharstream; icharstream strm(&(recv_buffer[0]), recv_buffer.size()); graphlab::iarchive iarc(strm); for(size_t i = 0; i < recv_data.size(); ++i) { iarc >> recv_data[i]; } #else logstream(LOG_FATAL) << "MPI not installed!" << std::endl; #endif } // end of mpi all to all
void gather(const T& elem, std::vector<T>& results) { #ifdef HAS_MPI // Get the mpi rank and size size_t mpi_size(size()); int mpi_rank(rank()); if(results.size() != mpi_size) results.resize(mpi_size); // Serialize the local map graphlab::charstream cstrm(128); graphlab::oarchive oarc(cstrm); oarc << elem; cstrm.flush(); char* send_buffer = cstrm->c_str(); int send_buffer_size = cstrm->size(); assert(send_buffer_size >= 0); // compute the sizes std::vector<int> recv_sizes(mpi_size, -1); // Compute the sizes int error = MPI_Gather(&send_buffer_size, // Send buffer 1, // send count MPI_INT, // send type &(recv_sizes[0]), // recvbuffer 1, // recvcount MPI_INT, // recvtype mpi_rank, // root rank MPI_COMM_WORLD); assert(error == MPI_SUCCESS); for(size_t i = 0; i < recv_sizes.size(); ++i) assert(recv_sizes[i] >= 0); // Construct offsets std::vector<int> recv_offsets(recv_sizes); int sum = 0, tmp = 0; for(size_t i = 0; i < recv_offsets.size(); ++i) { tmp = recv_offsets[i]; recv_offsets[i] = sum; sum += tmp; } // if necessary realloac recv_buffer std::vector<char> recv_buffer(sum); // recv all the maps error = MPI_Gatherv(send_buffer, // send buffer send_buffer_size, // how much to send MPI_BYTE, // send type &(recv_buffer[0]), // recv buffer &(recv_sizes[0]), // amount to recv // for each cpuess &(recv_offsets[0]), // where to place data MPI_BYTE, mpi_rank, // root rank MPI_COMM_WORLD); assert(error == MPI_SUCCESS); // Update the local map namespace bio = boost::iostreams; typedef bio::stream<bio::array_source> icharstream; icharstream strm(&(recv_buffer[0]), recv_buffer.size()); graphlab::iarchive iarc(strm); for(size_t i = 0; i < results.size(); ++i) { iarc >> results[i]; } #else logstream(LOG_FATAL) << "MPI not installed!" << std::endl; #endif } // end of gather
/* * 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 ); }
/* * Parse a PKCS#1 encoded private RSA key */ static int pk_parse_key_pkcs1_der( rsa_context *rsa, const unsigned char *key, size_t keylen ) { int ret; size_t len; unsigned char *p, *end; p = (unsigned char *) key; end = p + keylen; /* * This function parses the RSAPrivateKey (PKCS#1) * * RSAPrivateKey ::= SEQUENCE { * version Version, * modulus INTEGER, -- n * publicExponent INTEGER, -- e * privateExponent INTEGER, -- d * prime1 INTEGER, -- p * prime2 INTEGER, -- q * exponent1 INTEGER, -- d mod (p-1) * exponent2 INTEGER, -- d mod (q-1) * coefficient INTEGER, -- (inverse of q) mod p * otherPrimeInfos OtherPrimeInfos OPTIONAL * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } end = p + len; if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } if( rsa->ver != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_VERSION ); } if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) { rsa_free( rsa ); return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } rsa->len = mpi_size( &rsa->N ); if( p != end ) { rsa_free( rsa ); return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } if( ( ret = rsa_check_privkey( rsa ) ) != 0 ) { rsa_free( rsa ); return( ret ); } return( 0 ); }
/* * Parse one or more certificates and add them to the chain */ int x509_add_certs( x509_cert *chain, unsigned char *buf, int buflen ) { int ret, len; unsigned char *s1, *s2; unsigned char *p, *end; x509_cert *crt; crt = chain; while( crt->version != 0 ) crt = crt->next; /* * check if the certificate is encoded in base64 */ s1 = (unsigned char *) strstr( (char *) buf, "-----BEGIN CERTIFICATE-----" ); if( s1 != NULL ) { s2 = (unsigned char *) strstr( (char *) buf, "-----END CERTIFICATE-----" ); if( s2 == NULL || s2 <= s1 ) return( ERR_X509_CERT_INVALID_PEM ); s1 += 27; if( *s1 == '\r' ) s1++; if( *s1 == '\n' ) s1++; else return( ERR_X509_CERT_INVALID_PEM ); /* * get the DER data length and decode the buffer */ len = 0; ret = base64_decode( NULL, &len, s1, s2 - s1 ); if( ret == ERR_BASE64_INVALID_CHARACTER ) return( ERR_X509_CERT_INVALID_PEM | ret ); if( ( p = (unsigned char *) malloc( len ) ) == NULL ) return( 1 ); if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 ) { free( p ); return( ERR_X509_CERT_INVALID_PEM | ret ); } /* * update the buffer size and offset */ s2 += 25; if( *s2 == '\r' ) s2++; if( *s2 == '\n' ) s2++; else return( ERR_X509_CERT_INVALID_PEM ); buflen -= s2 - buf; buf = s2; } else { /* * nope, copy the raw DER data */ p = (unsigned char *) malloc( len = buflen ); if( p == NULL ) return( 1 ); memcpy( p, buf, buflen ); buflen = 0; } crt->raw.p = p; crt->raw.len = len; end = p + len; /* * Certificate ::= SEQUENCE { * tbsCertificate TBSCertificate, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT ); } if( len != (int) ( end - p ) ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ERR_ASN1_LENGTH_MISMATCH ); } /* * TBSCertificate ::= SEQUENCE { */ crt->tbs.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ret ); } end = p + len; crt->tbs.len = end - crt->tbs.p; /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } * * CertificateSerialNumber ::= INTEGER * * signature AlgorithmIdentifier */ if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 || ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } crt->version++; if( crt->version > 3 ) { x509_free_cert( crt ); return( ERR_X509_CERT_UNKNOWN_VERSION ); } if( crt->sig_oid1.len != 9 || memcmp( crt->sig_oid1.p, OID_PKCS1, 8 ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_UNKNOWN_SIG_ALG ); } if( crt->sig_oid1.p[8] < 2 || crt->sig_oid1.p[8] > 5 ) { x509_free_cert( crt ); return( ERR_X509_CERT_UNKNOWN_SIG_ALG ); } /* * issuer Name */ crt->issuer_raw.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ret ); } if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } crt->issuer_raw.len = p - crt->issuer_raw.p; /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } * */ if( ( ret = x509_get_dates( &p, end, &crt->valid_from, &crt->valid_to ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } /* * subject Name */ crt->subject_raw.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ret ); } if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } crt->subject_raw.len = p - crt->subject_raw.p; /* * SubjectPublicKeyInfo ::= SEQUENCE * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ret ); } if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid, &crt->rsa.N, &crt->rsa.E ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } crt->rsa.len = ( mpi_size( &crt->rsa.N ) + 7 ) >> 3; /* * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 * extensions [3] EXPLICIT Extensions OPTIONAL * -- If present, version shall be v3 */ if( crt->version == 2 || crt->version == 3 ) { ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); if( ret != 0 ) { x509_free_cert( crt ); return( ret ); } } if( crt->version == 2 || crt->version == 3 ) { ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); if( ret != 0 ) { x509_free_cert( crt ); return( ret ); } } if( crt->version == 3 ) { ret = x509_get_ext( &p, end, &crt->v3_ext, &crt->ca_istrue, &crt->max_pathlen ); if( ret != 0 ) { x509_free_cert( crt ); return( ret ); } } if( p != end ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ERR_ASN1_LENGTH_MISMATCH ); } end = crt->raw.p + crt->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, 9 ) != 0 ) { x509_free_cert( crt ); return( ERR_X509_CERT_SIG_MISMATCH ); } if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 ) { x509_free_cert( crt ); return( ret ); } if( p != end ) { x509_free_cert( crt ); return( ERR_X509_CERT_INVALID_FORMAT | ERR_ASN1_LENGTH_MISMATCH ); } crt->next = (x509_cert *) malloc( sizeof( x509_cert ) ); if( crt->next == NULL ) { x509_free_cert( crt ); return( 1 ); } crt = crt->next; memset( crt, 0, sizeof( x509_cert ) ); if( buflen > 0 ) return( x509_add_certs( crt, buf, buflen ) ); return( 0 ); }