void hmac_sha256_complete(const void *key, size_t keylen, const void *buf, size_t len, uint8_t *mac) { hmac_sha256_ctx ctx; hmac_sha256_init(&ctx, key, keylen); hmac_sha256_update(&ctx, buf, len); hmac_sha256_final(&ctx, mac); }
void hmac_sha256(unsigned char *key, unsigned int key_size, unsigned char *message, unsigned int message_len, unsigned char *mac, unsigned mac_size) { hmac_sha256_ctx ctx; hmac_sha256_init(&ctx, key, key_size); hmac_sha256_update(&ctx, message, message_len); hmac_sha256_final(&ctx, mac, mac_size); }
void hmac_sha256(struct hmac_sha256 *hmac, const void *k, size_t ksize, const void *d, size_t dsize) { struct hmac_sha256_ctx ctx; hmac_sha256_init(&ctx, k, ksize); hmac_sha256_update(&ctx, d, dsize); hmac_sha256_done(&ctx, hmac); }
void hmac_sha256(const char *msg, const unsigned int msg_len, unsigned char *hmac, const char *hmac_key, const int hmac_key_len) { hmac_sha256_ctx ctx; memset(&ctx, 0, sizeof(ctx)); hmac_sha256_init(&ctx, hmac_key, hmac_key_len); hmac_sha256_update(&ctx, msg, msg_len); hmac_sha256_final(&ctx, hmac); return; }
/* check an incoming signature */ NTSTATUS smb2_check_signature(struct smb2_request_buffer *buf, DATA_BLOB session_key) { uint64_t session_id; struct HMACSHA256Context m; uint8_t res[SHA256_DIGEST_LENGTH]; uint8_t sig[16]; size_t hdr_offset; if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) { /* can't check non-SMB2 messages */ return NT_STATUS_OK; } hdr_offset = buf->hdr - buf->buffer; session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID); if (session_id == 0) { /* don't sign messages with a zero session_id. See MS-SMB2 3.2.4.1.1 */ return NT_STATUS_OK; } if (session_key.length == 0) { /* we don't have the session key yet */ return NT_STATUS_OK; } memcpy(sig, buf->hdr+SMB2_HDR_SIGNATURE, 16); memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16); ZERO_STRUCT(m); hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m); hmac_sha256_update(buf->hdr, buf->size-hdr_offset, &m); hmac_sha256_final(res, &m); memcpy(buf->hdr+SMB2_HDR_SIGNATURE, sig, 16); if (memcmp(res, sig, 16) != 0) { DEBUG(0,("Bad SMB2 signature for message of size %u\n", (unsigned)buf->size-NBT_HDR_SIZE)); dump_data(0, sig, 16); dump_data(0, res, 16); return NT_STATUS_ACCESS_DENIED; } return NT_STATUS_OK; }
/* sign an outgoing message */ NTSTATUS smb2_sign_message(struct smb2_request_buffer *buf, DATA_BLOB session_key) { struct HMACSHA256Context m; uint8_t res[32]; uint64_t session_id; size_t hdr_offset; if (buf->size < NBT_HDR_SIZE + SMB2_HDR_SIGNATURE + 16) { /* can't sign non-SMB2 messages */ return NT_STATUS_OK; } hdr_offset = buf->hdr - buf->buffer; session_id = BVAL(buf->hdr, SMB2_HDR_SESSION_ID); if (session_id == 0) { /* we don't sign messages with a zero session_id. See MS-SMB2 3.2.4.1.1 */ return NT_STATUS_OK; } if (session_key.length == 0) { DEBUG(2,("Wrong session key length %u for SMB2 signing\n", (unsigned)session_key.length)); return NT_STATUS_ACCESS_DENIED; } memset(buf->hdr + SMB2_HDR_SIGNATURE, 0, 16); SIVAL(buf->hdr, SMB2_HDR_FLAGS, IVAL(buf->hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED); ZERO_STRUCT(m); hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m); hmac_sha256_update(buf->hdr, buf->size-hdr_offset, &m); hmac_sha256_final(res, &m); DEBUG(5,("signed SMB2 message of size %u\n", (unsigned)buf->size - NBT_HDR_SIZE)); memcpy(buf->hdr + SMB2_HDR_SIGNATURE, res, 16); return NT_STATUS_OK; }
/******************************************************************* Create a digest over the entire packet (including the data), and MD5 it with the session key. ********************************************************************/ static void netsec_do_sign(struct schannel_state *state, const uint8_t *confounder, const uint8_t *data, size_t length, uint8_t header[8], uint8_t *checksum) { if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { struct HMACSHA256Context ctx; hmac_sha256_init(state->creds->session_key, sizeof(state->creds->session_key), &ctx); if (confounder) { SSVAL(header, 0, NL_SIGN_HMAC_SHA256); SSVAL(header, 2, NL_SEAL_AES128); SSVAL(header, 4, 0xFFFF); SSVAL(header, 6, 0x0000); hmac_sha256_update(header, 8, &ctx); hmac_sha256_update(confounder, 8, &ctx); } else { SSVAL(header, 0, NL_SIGN_HMAC_SHA256); SSVAL(header, 2, NL_SEAL_NONE); SSVAL(header, 4, 0xFFFF); SSVAL(header, 6, 0x0000); hmac_sha256_update(header, 8, &ctx); } hmac_sha256_update(data, length, &ctx); hmac_sha256_final(checksum, &ctx); } else { uint8_t packet_digest[16]; static const uint8_t zeros[4]; MD5_CTX ctx; MD5Init(&ctx); MD5Update(&ctx, zeros, 4); if (confounder) { SSVAL(header, 0, NL_SIGN_HMAC_MD5); SSVAL(header, 2, NL_SEAL_RC4); SSVAL(header, 4, 0xFFFF); SSVAL(header, 6, 0x0000); MD5Update(&ctx, header, 8); MD5Update(&ctx, confounder, 8); } else { SSVAL(header, 0, NL_SIGN_HMAC_MD5); SSVAL(header, 2, NL_SEAL_NONE); SSVAL(header, 4, 0xFFFF); SSVAL(header, 6, 0x0000); MD5Update(&ctx, header, 8); } MD5Update(&ctx, data, length); MD5Final(packet_digest, &ctx); hmac_md5(state->creds->session_key, packet_digest, sizeof(packet_digest), checksum); } }