Skip to content

Commit acadf37

Browse files
committed
nvme: add windows support for rpmb hash functions
Moved hash functions used in RPMB into new util/hash.h with separate linux and windows implementations Signed-off-by: Brandon Capener <bcapener@micron.com>
1 parent 7a4eb8f commit acadf37

6 files changed

Lines changed: 242 additions & 131 deletions

File tree

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,7 @@ if want_nvme
602602
if host_system == 'windows'
603603
link_deps += [
604604
kernel32_dep,
605+
bcrypt_dep,
605606
]
606607
else
607608
link_args_list = ['-ldl']

nvme-rpmb.c

Lines changed: 6 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@
2323
#include <stdlib.h>
2424
#include <string.h>
2525
#include <unistd.h>
26-
27-
#include <linux/if_alg.h>
28-
#include <linux/socket.h>
29-
30-
#include <sys/socket.h>
3126
#include <sys/stat.h>
3227
#include <sys/types.h>
3328

@@ -37,129 +32,10 @@
3732
#include "nvme-cmds.h"
3833
#include "nvme-print.h"
3934
#include "nvme.h"
35+
#include "util/hash.h"
4036

4137
#define CREATE_CMD
4238

43-
44-
#ifndef AF_ALG
45-
#define AF_ALG 38
46-
#endif
47-
#ifndef SOL_ALG
48-
#define SOL_ALG 279
49-
#endif
50-
51-
#define HMAC_SHA256_ALGO_NAME "hmac(sha256)"
52-
#define MD5_HASH_ALGO_NAME "md5"
53-
#define HMAC_SHA256_HASH_SIZE 32
54-
#define MD5_HASH_HASH_SIZE 16
55-
56-
/*
57-
* Utility function to create hash value of given data (with given key) using
58-
* given hash algorithm; this function uses kernel crypto services
59-
*/
60-
unsigned char *create_hash(const char *algo,
61-
int hash_size,
62-
unsigned char *data,
63-
int datalen,
64-
unsigned char *key,
65-
int keylen)
66-
{
67-
int error, infd, outfd = -1;
68-
unsigned char *hash = NULL;
69-
struct sockaddr_alg provider_sa = {
70-
.salg_family = AF_ALG,
71-
.salg_type = "hash",
72-
.salg_name = { 0 }
73-
};
74-
75-
/* copy algorithm name */
76-
if (strlen(algo) > sizeof(provider_sa.salg_name)) {
77-
fprintf(stderr, "%s: algorithm name overflow", __func__);
78-
return hash;
79-
}
80-
memcpy(provider_sa.salg_name, algo, strlen(algo));
81-
82-
/* open netlink socket connection to algorigm provider and bind */
83-
infd = socket(AF_ALG, SOCK_SEQPACKET, 0);
84-
if (infd < 0) {
85-
perror("socket");
86-
return hash;
87-
}
88-
error = bind(infd, (struct sockaddr *)&provider_sa, sizeof(provider_sa));
89-
if (error < 0) {
90-
perror("bind");
91-
goto out_close_infd;
92-
}
93-
94-
/* if algorithm requires key, set it first - empty keys not accepted !*/
95-
if (key != NULL && keylen > 0) {
96-
error = setsockopt(infd, SOL_ALG, ALG_SET_KEY, key, keylen);
97-
if (error < 0) {
98-
perror("setsockopt");
99-
goto out_close_infd;
100-
}
101-
}
102-
103-
/* now send data to hash */
104-
outfd = accept(infd, NULL, 0);
105-
if (outfd < 0) {
106-
perror("accept");
107-
goto out_close_infd;
108-
}
109-
error = send(outfd, data, datalen, 0);
110-
if (error < 0) {
111-
perror("send");
112-
goto out_close_outfd;
113-
}
114-
115-
/* read computed hash */
116-
hash = (unsigned char *)calloc(hash_size, 1);
117-
if (hash == NULL) {
118-
perror("calloc");
119-
goto out_close_outfd;
120-
}
121-
122-
error = read(outfd, hash, hash_size);
123-
if (error != hash_size) {
124-
perror("read");
125-
free(hash);
126-
hash = NULL;
127-
}
128-
out_close_outfd:
129-
close(outfd);
130-
out_close_infd:
131-
close(infd);
132-
133-
return hash;
134-
}
135-
136-
/* Function that computes hmac-sha256 hash of given data and key pair. Returns
137-
* byte stream (non-null terminated) upon success, NULL otherwise.
138-
*/
139-
unsigned char *hmac_sha256(unsigned char *data, int datalen, unsigned char *key,
140-
int keylen)
141-
{
142-
return create_hash(HMAC_SHA256_ALGO_NAME,
143-
HMAC_SHA256_HASH_SIZE,
144-
data,
145-
datalen,
146-
key,
147-
keylen);
148-
}
149-
150-
/* Function that computes md5 of given buffer - md5 hash is used as nonce
151-
* Returns byte stream (non-null terminated) upon success, NULL otherwise.
152-
*/
153-
unsigned char *rpmb_md5(unsigned char *data, int datalen)
154-
{
155-
return create_hash(MD5_HASH_ALGO_NAME,
156-
MD5_HASH_HASH_SIZE,
157-
data,
158-
datalen,
159-
NULL,
160-
0);
161-
}
162-
16339
/* Read data from given file into buffer and return its length */
16440
static int read_file(const char *file, unsigned char **data, unsigned int *len)
16541
{
@@ -300,7 +176,7 @@ static int recv_rpmb_rsp(struct libnvme_transport_handle *hdl, int tgt, int size
300176
static void rpmb_nonce_init(struct rpmb_data_frame_t *req)
301177
{
302178
int num = rand();
303-
unsigned char *hash = rpmb_md5((unsigned char *)&num, sizeof(num));
179+
unsigned char *hash = create_md5((unsigned char *)&num, sizeof(num));
304180
if (hash) memcpy(req->nonce, hash, sizeof(req->nonce));
305181
}
306182

@@ -662,8 +538,8 @@ static int auth_data_write_chunk(struct libnvme_transport_handle *hdl,
662538
req->write_counter = write_cntr;
663539

664540
/* compute HMAC hash */
665-
mac = hmac_sha256(((unsigned char *)req + 223), req_size - 223,
666-
keybuf, keysize);
541+
mac = create_hmac_sha256(((unsigned char *)req + 223), req_size - 223,
542+
keybuf, keysize);
667543
if (mac == NULL) {
668544
fprintf(stderr, "failed to compute HMAC-SHA256\n");
669545
error = -1;
@@ -770,8 +646,8 @@ static int rpmb_write_config_block(struct libnvme_transport_handle *hdl,
770646

771647
free(cfg_buf_read);
772648
req->write_counter = write_cntr;
773-
mac = hmac_sha256(((unsigned char *)req + 223), req_size - 223,
774-
keybuf, keysize);
649+
mac = create_hmac_sha256(((unsigned char *)req + 223), req_size - 223,
650+
keybuf, keysize);
775651
if (mac == NULL) {
776652
fprintf(stderr, "failed to compute hmac-sha256 hash\n");
777653
error = -EINVAL;

util/hash-linux.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
#include <unistd.h>
6+
7+
#include <linux/if_alg.h>
8+
#include <linux/socket.h>
9+
10+
#include <sys/socket.h>
11+
12+
#include "hash.h"
13+
14+
#ifndef AF_ALG
15+
#define AF_ALG 38
16+
#endif
17+
#ifndef SOL_ALG
18+
#define SOL_ALG 279
19+
#endif
20+
21+
#define HMAC_SHA256_ALGO_NAME "hmac(sha256)"
22+
#define MD5_HASH_ALGO_NAME "md5"
23+
#define HMAC_SHA256_HASH_SIZE 32
24+
#define MD5_HASH_HASH_SIZE 16
25+
26+
/*
27+
* Utility function to create hash value of given data (with given key) using
28+
* given hash algorithm; this function uses kernel crypto services
29+
*/
30+
static unsigned char *create_hash(const char *algo, int hash_size,
31+
unsigned char *data, int datalen, unsigned char *key,
32+
int keylen)
33+
{
34+
int error, infd, outfd = -1;
35+
unsigned char *hash = NULL;
36+
struct sockaddr_alg provider_sa = {
37+
.salg_family = AF_ALG,
38+
.salg_type = "hash",
39+
.salg_name = { 0 }
40+
};
41+
42+
/* copy algorithm name */
43+
if (strlen(algo) > sizeof(provider_sa.salg_name)) {
44+
fprintf(stderr, "%s: algorithm name overflow", __func__);
45+
return hash;
46+
}
47+
memcpy(provider_sa.salg_name, algo, strlen(algo));
48+
49+
/* open netlink socket connection to algorigm provider and bind */
50+
infd = socket(AF_ALG, SOCK_SEQPACKET, 0);
51+
if (infd < 0) {
52+
perror("socket");
53+
return hash;
54+
}
55+
error = bind(infd, (struct sockaddr *)&provider_sa,
56+
sizeof(provider_sa));
57+
if (error < 0) {
58+
perror("bind");
59+
goto out_close_infd;
60+
}
61+
62+
/* if algorithm requires key, set it first - empty keys not accepted !*/
63+
if (key != NULL && keylen > 0) {
64+
error = setsockopt(infd, SOL_ALG, ALG_SET_KEY, key, keylen);
65+
if (error < 0) {
66+
perror("setsockopt");
67+
goto out_close_infd;
68+
}
69+
}
70+
71+
/* now send data to hash */
72+
outfd = accept(infd, NULL, 0);
73+
if (outfd < 0) {
74+
perror("accept");
75+
goto out_close_infd;
76+
}
77+
error = send(outfd, data, datalen, 0);
78+
if (error < 0) {
79+
perror("send");
80+
goto out_close_outfd;
81+
}
82+
83+
/* read computed hash */
84+
hash = (unsigned char *)calloc(hash_size, 1);
85+
if (hash == NULL) {
86+
perror("calloc");
87+
goto out_close_outfd;
88+
}
89+
90+
error = read(outfd, hash, hash_size);
91+
if (error != hash_size) {
92+
perror("read");
93+
free(hash);
94+
hash = NULL;
95+
}
96+
out_close_outfd:
97+
close(outfd);
98+
out_close_infd:
99+
close(infd);
100+
101+
return hash;
102+
}
103+
104+
/* Function that computes hmac-sha256 hash of given data and key pair. Returns
105+
* byte stream (non-null terminated) upon success, NULL otherwise.
106+
*/
107+
unsigned char *create_hmac_sha256(unsigned char *data, int datalen,
108+
unsigned char *key, int keylen)
109+
{
110+
return create_hash(HMAC_SHA256_ALGO_NAME,
111+
HMAC_SHA256_HASH_SIZE,
112+
data,
113+
datalen,
114+
key,
115+
keylen);
116+
}
117+
118+
/* Function that computes md5 of given buffer.
119+
* Returns byte stream (non-null terminated) upon success, NULL otherwise.
120+
*/
121+
unsigned char *create_md5(unsigned char *data, int datalen)
122+
{
123+
return create_hash(MD5_HASH_ALGO_NAME,
124+
MD5_HASH_HASH_SIZE,
125+
data,
126+
datalen,
127+
NULL,
128+
0);
129+
}

0 commit comments

Comments
 (0)