uint Sha::Finish(void *digest){ if(_bits==sha_160){ sha1_finish(tvcast<sha1_context>(_sha_ctx),(byte*)digest); }else if(_bits==sha_224||_bits==sha_256){ sha2_finish(tvcast<sha2_context>(_sha_ctx),(byte*)digest); }else if(_bits==sha_384||_bits==sha_512){ sha4_finish(tvcast<sha4_context>(_sha_ctx),(byte*)digest); }else{ _ASSERT(0); return 0; } return _bits; }
int entropy_func( void *data, unsigned char *output, size_t len ) { int ret, count = 0, i, reached; entropy_context *ctx = (entropy_context *) data; unsigned char buf[ENTROPY_BLOCK_SIZE]; if( len > ENTROPY_BLOCK_SIZE ) return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); /* * Always gather extra entropy before a call */ do { if( count++ > ENTROPY_MAX_LOOP ) return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); if( ( ret = entropy_gather( ctx ) ) != 0 ) return( ret ); reached = 0; for( i = 0; i < ctx->source_count; i++ ) if( ctx->source[i].size >= ctx->source[i].threshold ) reached++; } while( reached != ctx->source_count ); memset( buf, 0, ENTROPY_BLOCK_SIZE ); sha4_finish( &ctx->accumulator, buf ); /* * Perform second SHA-512 on entropy */ sha4( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); /* * Reset accumulator and counters and recycle existing entropy */ memset( &ctx->accumulator, 0, sizeof( sha4_context ) ); sha4_starts( &ctx->accumulator, 0 ); sha4_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); for( i = 0; i < ctx->source_count; i++ ) ctx->source[i].size = 0; memcpy( output, buf, len ); return( 0 ); }
// Retrieve the tag size_t mintls_hash_finish( mintls_hash_context * ctx, // (I/O) Context uint8_t * tag // (O) Tag ) { switch (ctx->type) { case MinTLS_SHA_160: return sha1_finish((struct sha1_ctx *)ctx,tag); case MinTLS_SHA_256: case MinTLS_SHA_224: return sha2_finish((struct sha2_ctx *)ctx,tag); case MinTLS_SHA_384: case MinTLS_SHA_512: return sha4_finish((struct sha4_ctx *)ctx,tag); default: return 0; } }
void sha512_finish_wrap( void *ctx, unsigned char *output ) { sha4_finish( (sha4_context *) ctx, output ); }
int message_rsa_decrypt(VCRYPT_CTX *ctx, rsa_context *public_rsa, uint8_t *ciphertext, size_t len, char **decrypted) { int ret = 0; int ret_len = 0; if (len < 5) return -ERR_DECRYPTION_ERROR; if (*ciphertext++ != VCRYPT_PROTOCOL_VERSION) return -ERR_DECRYPTION_ERROR; uint16_t encr_key_len = *((uint16_t*) ciphertext); ciphertext += 2; uint16_t sig_key_len = *((uint16_t*) ciphertext); ciphertext += 2; if (encr_key_len != ctx->ssl_req.rsa.len) return -ERR_DECRYPTION_ERROR; if ((len - 5 - sig_key_len) % encr_key_len) return -ERR_DECRYPTION_ERROR; int ciphertext_chunks = (len - 5 - sig_key_len) / encr_key_len; // maximum possible plaintext length int plain_len = ciphertext_chunks * ctx->ssl_req.rsa.len; if (ciphertext_chunks < 1) return -ERR_DECRYPTION_ERROR; // we need the signature too *decrypted = malloc(plain_len + 1); // 1 char for the null terminator if (!*decrypted) return -ERR_MALLOC; int chunk; size_t decrypted_len = 0; uint8_t *in = ciphertext, *out = (uint8_t*) *decrypted; for (chunk = 0; chunk < ciphertext_chunks; chunk++, out += decrypted_len, in += ctx->ssl_req.rsa.len) { if ((ret = rsa_pkcs1_decrypt(&ctx->ssl_req.rsa, RSA_PRIVATE, &decrypted_len, in, out, ctx->ssl_req.rsa.len)) != 0) { char err[256]; error_strerror(ret, err, sizeof err); dolog(0, " failed\n ! rsa_pkcs1_decrypt returned %d: %s (chunk: %d)\n", ret, err, chunk); free(*decrypted); return -ERR_DECRYPTION_ERROR; } ret_len += decrypted_len; } *out = 0; if (!public_rsa || !public_rsa->len) { return -ERR_SIGN_VERIFY_ERROR; } unsigned char hash[64]; sha4_context sha_ctx; sha4_starts(&sha_ctx, 1); sha4_update(&sha_ctx, (uint8_t*) *decrypted, ret_len); sha4_finish(&sha_ctx, hash); if ((ret = rsa_pkcs1_verify(public_rsa, RSA_PUBLIC, public_rsa->hash_id, sizeof hash, hash, in)) != 0) { char err[256]; error_strerror(ret, err, sizeof err); dolog(0, " failed\n ! rsa_pkcs1_verify returned %d: %s\nmessage was: %s\n", ret, err, *decrypted); return -ERR_SIGN_VERIFY_ERROR; } return ret_len; }
int message_rsa_encrypt(VCRYPT_CTX *ctx, rsa_context *public_rsa, const char *username, const char *message, VCRYPT_PACKET **packet) { int ret; /* * format: * 1 byte protocol version * 2 bytes encryption key size in bytes * 2 bytes signature key size in bytes * ciphertext * signature * */ if (!public_rsa->len) return -ERR_NO_PUBKEY; // we dont encrypt null terminating char, as this creates a vector of attack int plain_len = strlen(message); if (plain_len == 0) return -ERR_ENCRYPTION_ERROR; size_t plain_chunk_len = public_rsa->len - 11; // get packet size int plain_chunks = ceil(plain_len / (float) plain_chunk_len); int ciphertext_len = plain_chunks * public_rsa->len; // space for signature ciphertext_len += ctx->ssl_req.rsa.len; *packet = packet_new(DEST_CLIENT, username, REQ_MESSAGE_SEND, ciphertext_len + 5); if (!*packet) return -ERR_MALLOC; // TODO: add ciphertext stealing (form signature) to save bandwidth (i.e. use signature as padding) int chunk; int chunk_len; uint8_t *in = (uint8_t*) message, *out = (uint8_t*) (*packet)->payload; *out++ = VCRYPT_PROTOCOL_VERSION; *((uint16_t*) out) = public_rsa->len; out += 2; *((uint16_t*) out) = ctx->ssl_req.rsa.len; out += 2; for (chunk = 0; chunk < plain_chunks; chunk++, in += plain_chunk_len, out += public_rsa->len) { // last usually has different length chunk_len = chunk == plain_chunks - 1 ? plain_len % plain_chunk_len : plain_chunk_len; if ((ret = rsa_pkcs1_encrypt(public_rsa, ctr_drbg_random, &ctx->ssl_req.ctr_drbg, RSA_PUBLIC, chunk_len, in, out) != 0)) { free(packet); return -ERR_ENCRYPTION_ERROR; } } unsigned char hash[64]; sha4_context sha_ctx; sha4_starts(&sha_ctx, 1); sha4_update(&sha_ctx, (uint8_t*) message, plain_len); sha4_finish(&sha_ctx, hash); if ((ret = rsa_pkcs1_sign(&ctx->ssl_req.rsa, NULL, NULL, RSA_PRIVATE, ctx->ssl_req.rsa.hash_id, sizeof hash, hash, out) != 0)) { free(packet); return -ERR_SIGN_ERROR; } return 0; }
char* crypt_sha512_r(const char *key, const char *salt, size_t rounds, char *buffer, int buflen) { uint8_t alt_result[64], temp_result[64]; sha4_context ctx, alt_ctx; size_t salt_len, key_len, cnt; char *cp, *copied_key, *copied_salt, *p_bytes, *s_bytes; copied_key = NULL; copied_salt = NULL; salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX); key_len = strlen(key); /* Prepare for the real work. */ sha4_starts(&ctx, 0); /* Add the key string. */ sha4_update(&ctx, (unsigned char*)key, key_len); /* The last part is the salt string. This must be at most 8 * characters and it ends at the first `$' character (for * compatibility with existing implementations). */ sha4_update(&ctx, (unsigned char*)salt, salt_len); /* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The * final result will be added to the first context. */ sha4_starts(&alt_ctx, 0); /* Add key. */ sha4_update(&alt_ctx, (unsigned char*)key, key_len); /* Add salt. */ sha4_update(&alt_ctx, (unsigned char*)salt, salt_len); /* Add key again. */ sha4_update(&alt_ctx, (unsigned char*)key, key_len); /* Now get result of this (64 bytes) and add it to the other context. */ sha4_finish(&alt_ctx, alt_result); /* Add for any character in the key one byte of the alternate sum. */ for (cnt = key_len; cnt > 64; cnt -= 64) sha4_update(&ctx, (unsigned char*)alt_result, 64); sha4_update(&ctx, (unsigned char*)alt_result, cnt); /* Take the binary representation of the length of the key and for * every 1 add the alternate sum, for every 0 the key. */ for (cnt = key_len; cnt > 0; cnt >>= 1) if ((cnt & 1) != 0) sha4_update(&ctx, (unsigned char*)alt_result, 64); else sha4_update(&ctx, (unsigned char*)key, key_len); /* Create intermediate result. */ sha4_finish(&ctx, alt_result); /* Start computation of P byte sequence. */ sha4_starts(&alt_ctx, 0); /* For every character in the password add the entire password. */ for (cnt = 0; cnt < key_len; ++cnt) sha4_update(&alt_ctx, (unsigned char*)key, key_len); /* Finish the digest. */ sha4_finish(&alt_ctx, temp_result); /* Create byte sequence P. */ cp = p_bytes = alloca(key_len); for (cnt = key_len; cnt >= 64; cnt -= 64) { memcpy(cp, temp_result, 64); cp += 64; } memcpy(cp, temp_result, cnt); /* Start computation of S byte sequence. */ sha4_starts(&alt_ctx, 0); /* For every character in the password add the entire password. */ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) sha4_update(&alt_ctx, (unsigned char*)salt, salt_len); /* Finish the digest. */ sha4_finish(&alt_ctx, temp_result); /* Create byte sequence S. */ cp = s_bytes = alloca(salt_len); for (cnt = salt_len; cnt >= 64; cnt -= 64) { memcpy(cp, temp_result, 64); cp += 64; } memcpy(cp, temp_result, cnt); /* Repeatedly run the collected hash value through SHA512 to burn CPU * cycles. */ for (cnt = 0; cnt < rounds; ++cnt) { /* New context. */ sha4_starts(&ctx, 0); /* Add key or last result. */ if ((cnt & 1) != 0) sha4_update(&ctx, (unsigned char*)p_bytes, key_len); else sha4_update(&ctx, (unsigned char*)alt_result, 64); /* Add salt for numbers not divisible by 3. */ if (cnt % 3 != 0) sha4_update(&ctx, (unsigned char*)s_bytes, salt_len); /* Add key for numbers not divisible by 7. */ if (cnt % 7 != 0) sha4_update(&ctx, (unsigned char*)p_bytes, key_len); /* Add key or last result. */ if ((cnt & 1) != 0) sha4_update(&ctx, (unsigned char*)alt_result, 64); else sha4_update(&ctx, (unsigned char*)p_bytes, key_len); /* Create intermediate result. */ sha4_finish(&ctx, alt_result); } cp = buffer; b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4, &buflen, &cp); b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4, &buflen, &cp); b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4, &buflen, &cp); b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4, &buflen, &cp); b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4, &buflen, &cp); b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4, &buflen, &cp); b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4, &buflen, &cp); b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4, &buflen, &cp); b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4, &buflen, &cp); b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4, &buflen, &cp); b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4, &buflen, &cp); b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4, &buflen, &cp); b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4, &buflen, &cp); b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4, &buflen, &cp); b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4, &buflen, &cp); b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4, &buflen, &cp); b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4, &buflen, &cp); b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4, &buflen, &cp); b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4, &buflen, &cp); b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4, &buflen, &cp); b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4, &buflen, &cp); b64_from_24bit(0, 0, alt_result[63], 2, &buflen, &cp); if (buflen <= 0) { errno = ERANGE; buffer = NULL; } else *cp = '\0'; return buffer; }