/*********************** FUNCTION DEFINITIONS ***********************/ int md2_test() { BYTE text1[] = {"abc"}; BYTE text2[] = {"abcdefghijklmnopqrstuvwxyz"}; BYTE text3_1[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde"}; BYTE text3_2[] = {"fghijklmnopqrstuvwxyz0123456789"}; BYTE hash1[MD2_BLOCK_SIZE] = {0xda,0x85,0x3b,0x0d,0x3f,0x88,0xd9,0x9b,0x30,0x28,0x3a,0x69,0xe6,0xde,0xd6,0xbb}; BYTE hash2[MD2_BLOCK_SIZE] = {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab,0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b}; BYTE hash3[MD2_BLOCK_SIZE] = {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39,0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd}; BYTE buf[16]; MD2_CTX ctx; int pass = 1; md2_init(&ctx); md2_update(&ctx, text1, strlen(text1)); md2_final(&ctx, buf); pass = pass && !memcmp(hash1, buf, MD2_BLOCK_SIZE); // Note that the MD2 object can be re-used. md2_init(&ctx); md2_update(&ctx, text2, strlen(text2)); md2_final(&ctx, buf); pass = pass && !memcmp(hash2, buf, MD2_BLOCK_SIZE); // Note that the data is added in two chunks. md2_init(&ctx); md2_update(&ctx, text3_1, strlen(text3_1)); md2_update(&ctx, text3_2, strlen(text3_2)); md2_final(&ctx, buf); pass = pass && !memcmp(hash3, buf, MD2_BLOCK_SIZE); return(pass); }
/** * MD2 test fuction. * This function test MD2 algorithm with a standard string specified * in RFC 1319. * * \note This test work with official array of 256 byte pemutation * contructed from digits of pi, defined in the RFC 1319. * */ bool md2_test(void) { Md2Context context; const char *test[] = { "", "message digest", "abcdefghijklmnopqrstuvwxyz", "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }; const char *result[] = { "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69\x27\x73", "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe\x06\xb0", "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47\x94\x0b", "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3\xef\xd8", }; for (size_t i = 0; i < countof(test); i++) { md2_init(&context); md2_update(&context, test[i], strlen(test[i])); if(memcmp(result[i], md2_end(&context), MD2_DIGEST_LEN)) return false; } return true; }
/* * This function stir entropy pool with MD2 function hash. * */ static void randpool_stir(EntropyPool *pool) { size_t entropy = pool->entropy; //Save current calue of entropy. Md2Context context; uint8_t tmp_buf[((sizeof(size_t) * 2) + sizeof(int)) * 2 + 1]; //Temporary buffer. md2_init(&context); //Init MD2 algorithm. randpool_add(pool, NULL, 0); for (int i = 0; i < (CONFIG_SIZE_ENTROPY_POOL / MD2_DIGEST_LEN); i++) { sprintf((char *)tmp_buf, "%0x%0x%0x", pool->counter, i, pool->pos_add); /* * Hash with MD2 algorithm the entropy pool. */ md2_update(&context, pool->pool_entropy, CONFIG_SIZE_ENTROPY_POOL); md2_update(&context, tmp_buf, sizeof(tmp_buf) - 1); /*Insert a message digest in entropy pool.*/ randpool_push(pool, md2_end(&context), MD2_DIGEST_LEN); pool->counter = pool->counter + 1; } /*Insert in pool the difference between a two call of this function (see above).*/ randpool_add(pool, NULL, 0); pool->entropy = entropy; //Restore old value of entropy. We haven't add entropy. }
/* * output = MD2( file contents ) */ int md2_file( const char *path, unsigned char output[16] ) { FILE *f; size_t n; md2_context ctx; unsigned char buf[1024]; if( ( f = fopen( path, "rb" ) ) == NULL ) return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); md2_init( &ctx ); md2_starts( &ctx ); while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) md2_update( &ctx, buf, n ); md2_finish( &ctx, output ); md2_free( &ctx ); if( ferror( f ) != 0 ) { fclose( f ); return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); } fclose( f ); return( 0 ); }
/** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int md2_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[16]; } tests[] = { { "", {0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d, 0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73 } }, { "a", {0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72, 0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1 } }, { "message digest", {0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b, 0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0 } }, { "abcdefghijklmnopqrstuvwxyz", {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab, 0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b } }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39, 0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd } }, { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", {0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d, 0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8 } } }; int i; unsigned char tmp[16]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { md2_init(&md); md2_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); md2_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD2", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif }
void calc_md2(char *str,uint8_t *digest,uint8_t *message,int32_t len) { int init_hexbytes_noT(char *hexbytes,unsigned char *message,long len); hash_state md; md2_init(&md); md2_process(&md,message,len); md2_done(&md,digest); if ( str != 0 ) init_hexbytes_noT(str,digest,16); }
/* * output = MD2( input buffer ) */ void md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) { md2_context ctx; md2_init( &ctx ); md2_starts( &ctx ); md2_update( &ctx, input, ilen ); md2_finish( &ctx, output ); md2_free( &ctx ); }
void md2_digest(struct md2_ctx *ctx, unsigned length, uint8_t *digest) { unsigned left; assert(length <= MD2_DIGEST_SIZE); left = MD2_DATA_SIZE - ctx->index; memset(ctx->block + ctx->index, left, left); md2_transform(ctx, ctx->block); md2_transform(ctx, ctx->C); memcpy(digest, ctx->X, length); md2_init(ctx); }
/** * Get \param n_byte from entropy pool. If n_byte is larger than number * byte of entropy in entropy pool, randpool_get continue * to generate pseudocasual value from previous state of * pool. * \param n_byte number fo bytes to read. * \param pool is the pool entropy context. * \param _data is the pointer to write the random data to. */ void randpool_get(EntropyPool *pool, void *_data, size_t n_byte) { Md2Context context; size_t i = pool->pos_get; size_t n = n_byte; size_t pos_write = 0; //Number of block has been written in data. size_t len = MIN((size_t)MD2_DIGEST_LEN, n_byte); uint8_t *data; data = (uint8_t *)_data; /* Test if i + CONFIG_MD2_BLOCK_LEN is inside of entropy pool.*/ ASSERT((MD2_DIGEST_LEN + i) <= CONFIG_SIZE_ENTROPY_POOL); md2_init(&context); while(n > 0) { /*Hash previous state of pool*/ md2_update(&context, &pool->pool_entropy[i], MD2_DIGEST_LEN); memcpy(&data[pos_write], md2_end(&context), len); pos_write += len; //Update number of block has been written in data. n -= len; //Number of byte copied in data. len = MIN(n,(size_t)MD2_DIGEST_LEN); i = (i + MD2_DIGEST_LEN) % CONFIG_SIZE_ENTROPY_POOL; /* If we haven't more entropy pool to hash, we stir it.*/ if(i < MD2_DIGEST_LEN) { randpool_stir(pool); i = pool->pos_get; } } pool->pos_get = i; //Current number of byte we get from pool. pool->entropy -= n_byte; //Update a entropy. }
static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id ) { switch (alg_id) { case ALG_ID_MD2: md2_init( &hash->u.md2 ); break; case ALG_ID_MD4: MD4Init( &hash->u.md4 ); break; case ALG_ID_MD5: MD5Init( &hash->u.md5 ); break; case ALG_ID_SHA1: A_SHAInit( &hash->u.sha1 ); break; case ALG_ID_SHA256: sha256_init( &hash->u.sha256 ); break; case ALG_ID_SHA384: sha384_init( &hash->u.sha512 ); break; case ALG_ID_SHA512: sha512_init( &hash->u.sha512 ); break; default: ERR( "unhandled id %u\n", alg_id ); return STATUS_NOT_IMPLEMENTED; } return STATUS_SUCCESS; }
static int wrap_nettle_hash_init (gnutls_mac_algorithm_t algo, void **_ctx) { struct nettle_hash_ctx *ctx; ctx = gnutls_malloc (sizeof (struct nettle_hash_ctx)); if (ctx == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ctx->algo = algo; switch (algo) { case GNUTLS_DIG_MD5: md5_init (&ctx->ctx.md5); ctx->update = (update_func) md5_update; ctx->digest = (digest_func) md5_digest; ctx->ctx_ptr = &ctx->ctx.md5; ctx->length = MD5_DIGEST_SIZE; break; case GNUTLS_DIG_SHA1: sha1_init (&ctx->ctx.sha1); ctx->update = (update_func) sha1_update; ctx->digest = (digest_func) sha1_digest; ctx->ctx_ptr = &ctx->ctx.sha1; ctx->length = SHA1_DIGEST_SIZE; break; case GNUTLS_DIG_MD2: md2_init (&ctx->ctx.md2); ctx->update = (update_func) md2_update; ctx->digest = (digest_func) md2_digest; ctx->ctx_ptr = &ctx->ctx.md2; ctx->length = MD2_DIGEST_SIZE; break; case GNUTLS_DIG_SHA224: sha224_init (&ctx->ctx.sha224); ctx->update = (update_func) sha224_update; ctx->digest = (digest_func) sha224_digest; ctx->ctx_ptr = &ctx->ctx.sha224; ctx->length = SHA224_DIGEST_SIZE; break; case GNUTLS_DIG_SHA256: sha256_init (&ctx->ctx.sha256); ctx->update = (update_func) sha256_update; ctx->digest = (digest_func) sha256_digest; ctx->ctx_ptr = &ctx->ctx.sha256; ctx->length = SHA256_DIGEST_SIZE; break; case GNUTLS_DIG_SHA384: sha384_init (&ctx->ctx.sha384); ctx->update = (update_func) sha384_update; ctx->digest = (digest_func) sha384_digest; ctx->ctx_ptr = &ctx->ctx.sha384; ctx->length = SHA384_DIGEST_SIZE; break; case GNUTLS_DIG_SHA512: sha512_init (&ctx->ctx.sha512); ctx->update = (update_func) sha512_update; ctx->digest = (digest_func) sha512_digest; ctx->ctx_ptr = &ctx->ctx.sha512; ctx->length = SHA512_DIGEST_SIZE; break; default: gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } *_ctx = ctx; return 0; }
int assemble_ipmi_lan_pkt (fiid_obj_t obj_rmcp_hdr, fiid_obj_t obj_lan_session_hdr, fiid_obj_t obj_lan_msg_hdr, fiid_obj_t obj_cmd, const void *authentication_code_data, unsigned int authentication_code_data_len, void *pkt, unsigned int pkt_len, unsigned int flags) { uint8_t authentication_type; uint64_t val; unsigned int indx = 0; int required_len; void *authentication_code_field_ptr = NULL; void *checksum_data_ptr = NULL; void *msg_data_ptr = NULL; void *ipmi_msg_len_ptr = NULL; unsigned int msg_data_count = 0; unsigned int checksum_data_count = 0; uint8_t ipmi_msg_len; fiid_obj_t obj_lan_msg_trlr = NULL; uint8_t pwbuf[IPMI_1_5_MAX_PASSWORD_LENGTH]; uint8_t checksum; int len, rv = -1; unsigned int flags_mask = 0; if (!fiid_obj_valid (obj_rmcp_hdr) || !fiid_obj_valid (obj_lan_session_hdr) || !fiid_obj_valid (obj_lan_msg_hdr) || !fiid_obj_valid (obj_cmd) || (authentication_code_data && authentication_code_data_len > IPMI_1_5_MAX_PASSWORD_LENGTH) || !pkt || (flags & ~flags_mask)) { SET_ERRNO (EINVAL); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_rmcp_hdr, tmpl_rmcp_hdr) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_session_hdr, tmpl_lan_session_hdr) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_TEMPLATE_COMPARE (obj_lan_msg_hdr, tmpl_lan_msg_hdr_rq) < 0) { ERRNO_TRACE (errno); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_rmcp_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); return (-1); } /* * ipmi_msg_len is calculated in this function, so we can't use * fiid_obj_packet_valid() on obj_lan_session_hdr b/c ipmi_msg_len * is probably not set yet. */ if (FIID_OBJ_PACKET_VALID (obj_lan_msg_hdr) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr); return (-1); } if (FIID_OBJ_PACKET_VALID (obj_cmd) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); return (-1); } if (FIID_OBJ_GET (obj_lan_session_hdr, "authentication_type", &val) < 0) { ERRNO_TRACE (errno); return (-1); } authentication_type = val; if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE && authentication_type != IPMI_AUTHENTICATION_TYPE_MD2 && authentication_type != IPMI_AUTHENTICATION_TYPE_MD5 && authentication_type != IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY) { SET_ERRNO (EINVAL); return (-1); } /* no need for overflow checks, handled w/ _ipmi_lan_pkt_rq_min_size check */ required_len = _ipmi_lan_pkt_rq_min_size (authentication_type, obj_cmd); if (pkt_len < required_len) { SET_ERRNO (EMSGSIZE); return (-1); } memset (pkt, 0, pkt_len); if ((len = fiid_obj_get_all (obj_rmcp_hdr, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr); goto cleanup; } indx += len; if ((len = fiid_obj_get_block (obj_lan_session_hdr, "authentication_type", "session_id", pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); goto cleanup; } indx += len; /* authentication_code generated last. Save pointers for later calculation */ if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE) { authentication_code_field_ptr = (pkt + indx); indx += IPMI_1_5_MAX_PASSWORD_LENGTH; } ipmi_msg_len_ptr = (pkt + indx); if ((len = fiid_template_field_len_bytes (tmpl_lan_session_hdr, "ipmi_msg_len")) < 0) { ERRNO_TRACE (errno); goto cleanup; } if (len != 1) { SET_ERRNO (EINVAL); goto cleanup; } indx += len; msg_data_ptr = (pkt + indx); if ((len = fiid_obj_get_block (obj_lan_msg_hdr, "rs_addr", "checksum1", pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr); goto cleanup; } indx += len; msg_data_count += len; checksum_data_ptr = (pkt + indx); if ((len = fiid_obj_get_block (obj_lan_msg_hdr, "rq_addr", "rq_seq", pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr); goto cleanup; } indx += len; msg_data_count += len; checksum_data_count += len; if ((len = fiid_obj_get_all (obj_cmd, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd); goto cleanup; } indx += len; msg_data_count += len; checksum_data_count += len; if (!(obj_lan_msg_trlr = fiid_obj_create (tmpl_lan_msg_trlr))) { ERRNO_TRACE (errno); goto cleanup; } checksum = ipmi_checksum (checksum_data_ptr, checksum_data_count); if (fiid_obj_set_all (obj_lan_msg_trlr, &checksum, sizeof (checksum)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr); goto cleanup; } if ((len = fiid_obj_get_all (obj_lan_msg_trlr, pkt + indx, pkt_len - indx)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr); goto cleanup; } indx += len; msg_data_count += len; /* ipmi_msg_len done after message length is computed */ ipmi_msg_len = msg_data_count; memcpy (ipmi_msg_len_ptr, &ipmi_msg_len, sizeof (ipmi_msg_len)); /* Auth code must be done last, some authentication like md2 and md5 * require all fields, including checksums, to be calculated * beforehand */ if (authentication_type != IPMI_AUTHENTICATION_TYPE_NONE) { int authentication_len; memset (pwbuf, '\0', IPMI_1_5_MAX_PASSWORD_LENGTH); if ((authentication_len = fiid_obj_field_len_bytes (obj_lan_session_hdr, "authentication_code")) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); goto cleanup; } if (authentication_len) { if (fiid_obj_get_data (obj_lan_session_hdr, "authentication_code", pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); goto cleanup; } memcpy (authentication_code_field_ptr, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); } else { if (authentication_code_data) memcpy (pwbuf, authentication_code_data, authentication_code_data_len); if (authentication_type == IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY) { memcpy (authentication_code_field_ptr, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); } else /* IPMI_AUTHENTICATION_TYPE_MD2 || IPMI_AUTHENTICATION_TYPE_MD5 */ { uint8_t session_id_buf[1024]; uint8_t session_sequence_number_buf[1024]; int session_id_len, session_sequence_number_len; if ((session_id_len = fiid_obj_get_data (obj_lan_session_hdr, "session_id", session_id_buf, 1024)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); goto cleanup; } if ((session_sequence_number_len = fiid_obj_get_data (obj_lan_session_hdr, "session_sequence_number", session_sequence_number_buf, 1024)) < 0) { FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_session_hdr); goto cleanup; } if (authentication_type == IPMI_AUTHENTICATION_TYPE_MD2) { md2_t ctx; uint8_t digest[MD2_DIGEST_LENGTH]; assert (IPMI_1_5_MAX_PASSWORD_LENGTH == MD2_DIGEST_LENGTH); md2_init (&ctx); md2_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); md2_update_data (&ctx, session_id_buf, session_id_len); md2_update_data (&ctx, msg_data_ptr, msg_data_count); md2_update_data (&ctx, session_sequence_number_buf, session_sequence_number_len); md2_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); md2_finish (&ctx, digest, MD2_DIGEST_LENGTH); md2_init (&ctx); memcpy (authentication_code_field_ptr, digest, IPMI_1_5_MAX_PASSWORD_LENGTH); secure_memset (digest, '\0', MD2_DIGEST_LENGTH); } else if (authentication_type == IPMI_AUTHENTICATION_TYPE_MD5) { md5_t ctx; uint8_t digest[MD5_DIGEST_LENGTH]; assert (IPMI_1_5_MAX_PASSWORD_LENGTH == MD5_DIGEST_LENGTH); md5_init (&ctx); md5_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); md5_update_data (&ctx, session_id_buf, session_id_len); md5_update_data (&ctx, msg_data_ptr, msg_data_count); md5_update_data (&ctx, session_sequence_number_buf, session_sequence_number_len); md5_update_data (&ctx, pwbuf, IPMI_1_5_MAX_PASSWORD_LENGTH); md5_finish (&ctx, digest, MD5_DIGEST_LENGTH); md5_init (&ctx); memcpy (authentication_code_field_ptr, digest, IPMI_1_5_MAX_PASSWORD_LENGTH); secure_memset (digest, '\0', MD5_DIGEST_LENGTH); } } } } if (indx > INT_MAX) { SET_ERRNO (EMSGSIZE); goto cleanup; } rv = indx; cleanup: if (rv < 0) secure_memset (pkt, '\0', pkt_len); fiid_obj_destroy (obj_lan_msg_trlr); secure_memset (pwbuf, '\0', IPMI_1_5_MAX_PASSWORD_LENGTH); return (rv); }