/* * Make a new empty bigint. It may just use an old one if one is available. * Otherwise get one off the heap. */ static bigint * ICACHE_FLASH_ATTR alloc(BI_CTX *ctx, int size) { bigint *biR; /* Can we recycle an old bigint? */ if (ctx->free_list != NULL) { biR = ctx->free_list; ctx->free_list = biR->next; ctx->free_count--; if (biR->refs != 0) { #ifdef CONFIG_SSL_FULL_MODE ssl_printf("alloc: refs was not 0\n"); #endif return biR; /* wujg : org ----> abort(); */ } more_comps(biR, size); } else { /* No free bigints available - create a new one. */ biR = (bigint *)SSL_MALLOC(sizeof(bigint)); biR->comps = (comp*)SSL_MALLOC(size * COMP_BYTE_SIZE); biR->max_comps = size; /* give some space to spare */ } biR->size = size; biR->refs = 1; biR->next = NULL; ctx->active_count++; return biR; }
/** * @brief Use PKCS1.5 for decryption/verification. * @param ctx [in] The context * @param in_data [in] The data to decrypt (must be < modulus size-11) * @param out_data [out] The decrypted data. * @param out_len [int] The size of the decrypted buffer in bytes * @param is_decryption [in] Decryption or verify operation. * @return The number of bytes that were originally encrypted. -1 on error. * @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125 */ int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data, int out_len, int is_decryption) { const int byte_size = ctx->num_octets; int i = 0, size; bigint *decrypted_bi, *dat_bi; uint8_t *block = (uint8_t *)SSL_MALLOC(byte_size); int pad_count = 0; if (out_len < byte_size) /* check output has enough size */ return -1; memset(out_data, 0, out_len); /* initialise */ /* decrypt */ dat_bi = bi_import(ctx->bi_ctx, in_data, byte_size); #ifdef CONFIG_SSL_CERT_VERIFICATION decrypted_bi = is_decryption ? /* decrypt or verify? */ RSA_private(ctx, dat_bi) : RSA_public(ctx, dat_bi); #else /* always a decryption */ decrypted_bi = RSA_private(ctx, dat_bi); #endif /* convert to a normal block */ bi_export(ctx->bi_ctx, decrypted_bi, block, byte_size); if (block[i++] != 0) /* leading 0? */ return -1; #ifdef CONFIG_SSL_CERT_VERIFICATION if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */ { if (block[i++] != 0x01) /* BT correct? */ return -1; while (block[i++] == 0xff && i < byte_size) pad_count++; } else /* PKCS1.5 encryption padding is random */ #endif { if (block[i++] != 0x02) /* BT correct? */ return -1; while (block[i++] && i < byte_size) pad_count++; } /* check separator byte 0x00 - and padding must be 8 or more bytes */ if (i == byte_size || pad_count < 8) return -1; size = byte_size - i; /* get only the bit we want */ if (size > 0) memcpy(out_data, &block[i], size); SSL_FREE(block); return size ? size : -1; }
/** * Obtain an ASN.1 printable string type. */ static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str) { int len = X509_NOT_OK; int asn1_type = buf[*offset]; /* some certs have this awful crud in them for some reason */ if (asn1_type != ASN1_PRINTABLE_STR && asn1_type != ASN1_PRINTABLE_STR2 && asn1_type != ASN1_TELETEX_STR && asn1_type != ASN1_IA5_STR && asn1_type != ASN1_UNICODE_STR) goto end_pnt_str; (*offset)++; len = get_asn1_length(buf, offset); if (asn1_type == ASN1_UNICODE_STR) { int i; *str = (char *)SSL_MALLOC(len/2+1); /* allow for null */ for (i = 0; i < len; i += 2) (*str)[i/2] = buf[*offset + i + 1]; (*str)[len/2] = 0; /* null terminate */ } else { *str = (char *)SSL_MALLOC(len+1); /* allow for null */ memcpy(*str, &buf[*offset], len); (*str)[len] = 0; /* null terminate */ } *offset += len; end_pnt_str: return len; }
/** * Read the signature of the certificate. */ int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx) { int ret = X509_NOT_OK; if (cert[(*offset)++] != ASN1_BIT_STRING) goto end_sig; x509_ctx->sig_len = get_asn1_length(cert, offset)-1; (*offset)++; /* ignore bit string padding bits */ x509_ctx->signature = (uint8_t *)SSL_MALLOC(x509_ctx->sig_len); memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len); *offset += x509_ctx->sig_len; ret = X509_OK; end_sig: return ret; }
/** * Read an integer value for ASN.1 data * Note: This function allocates memory which must be freed by the user. */ int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object) { int len; if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0) goto end_int_array; if (len > 1 && buf[*offset] == 0x00) /* ignore the negative byte */ { len--; (*offset)++; } *object = (uint8_t *)SSL_MALLOC(len); memcpy(*object, &buf[*offset], len); *offset += len; end_int_array: return len; }
/* * Work out g1, g3, g5, g7... etc for the sliding-window algorithm */ static void ICACHE_FLASH_ATTR precompute_slide_window(BI_CTX *ctx, int window, bigint *g1) { int k = 1, i; bigint *g2; for (i = 0; i < window-1; i++) /* compute 2^(window-1) */ { k <<= 1; } ctx->g = (bigint **)SSL_MALLOC(k*sizeof(bigint *)); ctx->g[0] = bi_clone(ctx, g1); bi_permanent(ctx->g[0]); g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0])); /* g^2 */ for (i = 1; i < k; i++) { ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i-1], bi_copy(g2))); bi_permanent(ctx->g[i]); } bi_free(ctx, g2); ctx->window = k; }
/** * @brief Perform a modular exponentiation. * * This function requires bi_set_mod() to have been called previously. This is * one of the optimisations used for performance. * @param ctx [in] The bigint session context. * @param bi [in] The bigint on which to perform the mod power operation. * @param biexp [in] The bigint exponent. * @return The result of the mod exponentiation operation * @see bi_set_mod(). */ bigint * ICACHE_FLASH_ATTR bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) { int i = find_max_exp_index(biexp), j, window_size = 1; bigint *biR = int_to_bi(ctx, 1); #if defined(CONFIG_BIGINT_MONTGOMERY) uint8_t mod_offset = ctx->mod_offset; if (!ctx->use_classical) { /* preconvert */ bi = bi_mont(ctx, bi_multiply(ctx, bi, ctx->bi_RR_mod_m[mod_offset])); /* x' */ bi_free(ctx, biR); biR = ctx->bi_R_mod_m[mod_offset]; /* A */ } #endif check(bi); check(biexp); #ifdef CONFIG_BIGINT_SLIDING_WINDOW for (j = i; j > 32; j /= 5) /* work out an optimum size */ window_size++; /* work out the slide constants */ precompute_slide_window(ctx, window_size, bi); #else /* just one constant */ ctx->g = (bigint **)SSL_MALLOC(sizeof(bigint *)); ctx->g[0] = bi_clone(ctx, bi); ctx->window = 1; bi_permanent(ctx->g[0]); #endif /* if sliding-window is off, then only one bit will be done at a time and * will reduce to standard left-to-right exponentiation */ do { if (exp_bit_is_one(biexp, i)) { int l = i-window_size+1; int part_exp = 0; if (l < 0) /* LSB of exponent will always be 1 */ l = 0; else { while (exp_bit_is_one(biexp, l) == 0) l++; /* go back up */ } /* build up the section of the exponent */ for (j = i; j >= l; j--) { biR = bi_residue(ctx, bi_square(ctx, biR)); if (exp_bit_is_one(biexp, j)) part_exp++; if (j != l) part_exp <<= 1; } part_exp = (part_exp-1)/2; /* adjust for array */ biR = bi_residue(ctx, bi_multiply(ctx, biR, ctx->g[part_exp])); i = l-1; } else /* square it */ { biR = bi_residue(ctx, bi_square(ctx, biR)); i--; } } while (i >= 0); /* cleanup */ for (i = 0; i < ctx->window; i++) { bi_depermanent(ctx->g[i]); bi_free(ctx, ctx->g[i]); } SSL_FREE(ctx->g); bi_free(ctx, bi); bi_free(ctx, biexp); #if defined CONFIG_BIGINT_MONTGOMERY return ctx->use_classical ? biR : bi_mont(ctx, biR); /* convert back */ #else /* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */ return biR; #endif }
/** * Set up AES with the key/iv and cipher size. */ void ICACHE_FLASH_ATTR AES_set_key(AES_CTX *ctx, const uint8_t *key, const uint8_t *iv, AES_MODE mode) { int i, ii; uint32_t *W, tmp, tmp2; unsigned char *ip; int words; unsigned char *Rcon_ram = (unsigned char *)SSL_MALLOC(32); switch (mode) { case AES_MODE_128: i = 10; words = 4; break; case AES_MODE_256: i = 14; words = 8; break; default: /* fail silently */ return; } ctx->rounds = i; ctx->key_size = words; W = ctx->ks; for (i = 0; i < words; i+=2) { W[i+0]= ((uint32_t)key[ 0]<<24)| ((uint32_t)key[ 1]<<16)| ((uint32_t)key[ 2]<< 8)| ((uint32_t)key[ 3] ); W[i+1]= ((uint32_t)key[ 4]<<24)| ((uint32_t)key[ 5]<<16)| ((uint32_t)key[ 6]<< 8)| ((uint32_t)key[ 7] ); key += 8; } // ip = Rcon; ip = Rcon_ram; memcpy(ip, Rcon, 32); // align, copy two byte more ii = 4 * (ctx->rounds+1); for (i = words; i<ii; i++) { tmp = W[i-1]; if ((i % words) == 0) { tmp2 =(uint32_t)system_get_data_of_array_8(aes_sbox, (tmp )&0xff)<< 8; tmp2|=(uint32_t)system_get_data_of_array_8(aes_sbox, (tmp>> 8)&0xff)<<16; tmp2|=(uint32_t)system_get_data_of_array_8(aes_sbox, (tmp>>16)&0xff)<<24; tmp2|=(uint32_t)system_get_data_of_array_8(aes_sbox, (tmp>>24) ); tmp=tmp2^(((unsigned int)*ip)<<24); ip++; } if ((words == 8) && ((i % words) == 4)) { tmp2 =(uint32_t)system_get_data_of_array_8(aes_sbox, (tmp )&0xff) ; tmp2|=(uint32_t)system_get_data_of_array_8(aes_sbox, (tmp>> 8)&0xff)<< 8; tmp2|=(uint32_t)system_get_data_of_array_8(aes_sbox, (tmp>>16)&0xff)<<16; tmp2|=(uint32_t)system_get_data_of_array_8(aes_sbox, (tmp>>24) )<<24; tmp=tmp2; }