Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,7 @@ if want_nvme
if host_system == 'windows'
link_deps += [
kernel32_dep,
bcrypt_dep,
]
else
link_args_list = ['-ldl']
Expand Down
136 changes: 6 additions & 130 deletions nvme-rpmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <linux/if_alg.h>
#include <linux/socket.h>

#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>

Expand All @@ -37,129 +32,10 @@
#include "nvme-cmds.h"
#include "nvme-print.h"
#include "nvme.h"
#include "util/hash.h"

#define CREATE_CMD


#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif

#define HMAC_SHA256_ALGO_NAME "hmac(sha256)"
#define MD5_HASH_ALGO_NAME "md5"
#define HMAC_SHA256_HASH_SIZE 32
#define MD5_HASH_HASH_SIZE 16

/*
* Utility function to create hash value of given data (with given key) using
* given hash algorithm; this function uses kernel crypto services
*/
unsigned char *create_hash(const char *algo,
int hash_size,
unsigned char *data,
int datalen,
unsigned char *key,
int keylen)
{
int error, infd, outfd = -1;
unsigned char *hash = NULL;
struct sockaddr_alg provider_sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
.salg_name = { 0 }
};

/* copy algorithm name */
if (strlen(algo) > sizeof(provider_sa.salg_name)) {
fprintf(stderr, "%s: algorithm name overflow", __func__);
return hash;
}
memcpy(provider_sa.salg_name, algo, strlen(algo));

/* open netlink socket connection to algorigm provider and bind */
infd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (infd < 0) {
perror("socket");
return hash;
}
error = bind(infd, (struct sockaddr *)&provider_sa, sizeof(provider_sa));
if (error < 0) {
perror("bind");
goto out_close_infd;
}

/* if algorithm requires key, set it first - empty keys not accepted !*/
if (key != NULL && keylen > 0) {
error = setsockopt(infd, SOL_ALG, ALG_SET_KEY, key, keylen);
if (error < 0) {
perror("setsockopt");
goto out_close_infd;
}
}

/* now send data to hash */
outfd = accept(infd, NULL, 0);
if (outfd < 0) {
perror("accept");
goto out_close_infd;
}
error = send(outfd, data, datalen, 0);
if (error < 0) {
perror("send");
goto out_close_outfd;
}

/* read computed hash */
hash = (unsigned char *)calloc(hash_size, 1);
if (hash == NULL) {
perror("calloc");
goto out_close_outfd;
}

error = read(outfd, hash, hash_size);
if (error != hash_size) {
perror("read");
free(hash);
hash = NULL;
}
out_close_outfd:
close(outfd);
out_close_infd:
close(infd);

return hash;
}

/* Function that computes hmac-sha256 hash of given data and key pair. Returns
* byte stream (non-null terminated) upon success, NULL otherwise.
*/
unsigned char *hmac_sha256(unsigned char *data, int datalen, unsigned char *key,
int keylen)
{
return create_hash(HMAC_SHA256_ALGO_NAME,
HMAC_SHA256_HASH_SIZE,
data,
datalen,
key,
keylen);
}

/* Function that computes md5 of given buffer - md5 hash is used as nonce
* Returns byte stream (non-null terminated) upon success, NULL otherwise.
*/
unsigned char *rpmb_md5(unsigned char *data, int datalen)
{
return create_hash(MD5_HASH_ALGO_NAME,
MD5_HASH_HASH_SIZE,
data,
datalen,
NULL,
0);
}

/* Read data from given file into buffer and return its length */
static int read_file(const char *file, unsigned char **data, unsigned int *len)
{
Expand Down Expand Up @@ -300,7 +176,7 @@ static int recv_rpmb_rsp(struct libnvme_transport_handle *hdl, int tgt, int size
static void rpmb_nonce_init(struct rpmb_data_frame_t *req)
{
int num = rand();
unsigned char *hash = rpmb_md5((unsigned char *)&num, sizeof(num));
unsigned char *hash = create_md5((unsigned char *)&num, sizeof(num));
if (hash) memcpy(req->nonce, hash, sizeof(req->nonce));
}

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

/* compute HMAC hash */
mac = hmac_sha256(((unsigned char *)req + 223), req_size - 223,
keybuf, keysize);
mac = create_hmac_sha256(((unsigned char *)req + 223), req_size - 223,
keybuf, keysize);
if (mac == NULL) {
fprintf(stderr, "failed to compute HMAC-SHA256\n");
error = -1;
Expand Down Expand Up @@ -770,8 +646,8 @@ static int rpmb_write_config_block(struct libnvme_transport_handle *hdl,

free(cfg_buf_read);
req->write_counter = write_cntr;
mac = hmac_sha256(((unsigned char *)req + 223), req_size - 223,
keybuf, keysize);
mac = create_hmac_sha256(((unsigned char *)req + 223), req_size - 223,
keybuf, keysize);
if (mac == NULL) {
fprintf(stderr, "failed to compute hmac-sha256 hash\n");
error = -EINVAL;
Expand Down
129 changes: 129 additions & 0 deletions util/hash-linux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <linux/if_alg.h>
#include <linux/socket.h>

#include <sys/socket.h>

#include "hash.h"

#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif

#define HMAC_SHA256_ALGO_NAME "hmac(sha256)"
#define MD5_HASH_ALGO_NAME "md5"
#define HMAC_SHA256_HASH_SIZE 32
#define MD5_HASH_HASH_SIZE 16

/*
* Utility function to create hash value of given data (with given key) using
* given hash algorithm; this function uses kernel crypto services
*/
static unsigned char *create_hash(const char *algo, int hash_size,
unsigned char *data, int datalen, unsigned char *key,
int keylen)
{
int error, infd, outfd = -1;
unsigned char *hash = NULL;
struct sockaddr_alg provider_sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
.salg_name = { 0 }
};

/* copy algorithm name */
if (strlen(algo) > sizeof(provider_sa.salg_name)) {
fprintf(stderr, "%s: algorithm name overflow", __func__);
return hash;
}
memcpy(provider_sa.salg_name, algo, strlen(algo));

/* open netlink socket connection to algorigm provider and bind */
infd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (infd < 0) {
perror("socket");
return hash;
}
error = bind(infd, (struct sockaddr *)&provider_sa,
sizeof(provider_sa));
if (error < 0) {
perror("bind");
goto out_close_infd;
}

/* if algorithm requires key, set it first - empty keys not accepted !*/
if (key != NULL && keylen > 0) {
error = setsockopt(infd, SOL_ALG, ALG_SET_KEY, key, keylen);
if (error < 0) {
perror("setsockopt");
goto out_close_infd;
}
}

/* now send data to hash */
outfd = accept(infd, NULL, 0);
if (outfd < 0) {
perror("accept");
goto out_close_infd;
}
error = send(outfd, data, datalen, 0);
if (error < 0) {
perror("send");
goto out_close_outfd;
}

/* read computed hash */
hash = (unsigned char *)calloc(hash_size, 1);
if (hash == NULL) {
perror("calloc");
goto out_close_outfd;
}

error = read(outfd, hash, hash_size);
if (error != hash_size) {
perror("read");
free(hash);
hash = NULL;
}
out_close_outfd:
close(outfd);
out_close_infd:
close(infd);

return hash;
}

/* Function that computes hmac-sha256 hash of given data and key pair. Returns
* byte stream (non-null terminated) upon success, NULL otherwise.
*/
unsigned char *create_hmac_sha256(unsigned char *data, int datalen,
unsigned char *key, int keylen)
{
return create_hash(HMAC_SHA256_ALGO_NAME,
HMAC_SHA256_HASH_SIZE,
data,
datalen,
key,
keylen);
}

/* Function that computes md5 of given buffer.
* Returns byte stream (non-null terminated) upon success, NULL otherwise.
*/
unsigned char *create_md5(unsigned char *data, int datalen)
{
return create_hash(MD5_HASH_ALGO_NAME,
MD5_HASH_HASH_SIZE,
data,
datalen,
NULL,
0);
}
Loading
Loading