1 /* 2 * CDDL HEADER START 3 * 4 * This file and its contents are supplied under the terms of the 5 * Common Development and Distribution License ("CDDL"), version 1.0. 6 * You may only use this file in accordance with the terms of version 7 * 1.0 of the CDDL. 8 * 9 * A full copy of the text of the CDDL should have accompanied this 10 * source. A copy of the CDDL is also available via the Internet at 11 * http://www.illumos.org/license/CDDL. 12 * 13 * CDDL HEADER END 14 */ 15 16 /* 17 * Copyright (c) 2017, Datto, Inc. All rights reserved. 18 */ 19 20 #include <sys/crypto/api.h> 21 #include <sys/sha2.h> 22 #include <sys/hkdf.h> 23 24 static int 25 hkdf_sha512_extract(uint8_t *salt, uint_t salt_len, uint8_t *key_material, 26 uint_t km_len, uint8_t *out_buf) 27 { 28 int ret; 29 crypto_mechanism_t mech; 30 crypto_key_t key; 31 crypto_data_t input_cd, output_cd; 32 33 /* initialize HMAC mechanism */ 34 mech.cm_type = crypto_mech2id(SUN_CKM_SHA512_HMAC); 35 mech.cm_param = NULL; 36 mech.cm_param_len = 0; 37 38 /* initialize the salt as a crypto key */ 39 key.ck_length = CRYPTO_BYTES2BITS(salt_len); 40 key.ck_data = salt; 41 42 /* initialize crypto data for the input and output data */ 43 input_cd.cd_format = CRYPTO_DATA_RAW; 44 input_cd.cd_offset = 0; 45 input_cd.cd_length = km_len; 46 input_cd.cd_raw.iov_base = (char *)key_material; 47 input_cd.cd_raw.iov_len = input_cd.cd_length; 48 49 output_cd.cd_format = CRYPTO_DATA_RAW; 50 output_cd.cd_offset = 0; 51 output_cd.cd_length = SHA512_DIGEST_LENGTH; 52 output_cd.cd_raw.iov_base = (char *)out_buf; 53 output_cd.cd_raw.iov_len = output_cd.cd_length; 54 55 ret = crypto_mac(&mech, &input_cd, &key, NULL, &output_cd); 56 if (ret != CRYPTO_SUCCESS) 57 return (SET_ERROR(EIO)); 58 59 return (0); 60 } 61 62 static int 63 hkdf_sha512_expand(uint8_t *extract_key, uint8_t *info, uint_t info_len, 64 uint8_t *out_buf, uint_t out_len) 65 { 66 int ret; 67 crypto_mechanism_t mech; 68 crypto_context_t ctx; 69 crypto_key_t key; 70 crypto_data_t T_cd, info_cd, c_cd; 71 uint_t i, T_len = 0, pos = 0; 72 uint8_t c; 73 uint_t N = (out_len + SHA512_DIGEST_LENGTH) / SHA512_DIGEST_LENGTH; 74 uint8_t T[SHA512_DIGEST_LENGTH]; 75 76 if (N > 255) 77 return (SET_ERROR(EINVAL)); 78 79 /* initialize HMAC mechanism */ 80 mech.cm_type = crypto_mech2id(SUN_CKM_SHA512_HMAC); 81 mech.cm_param = NULL; 82 mech.cm_param_len = 0; 83 84 /* initialize the salt as a crypto key */ 85 key.ck_length = CRYPTO_BYTES2BITS(SHA512_DIGEST_LENGTH); 86 key.ck_data = extract_key; 87 88 /* initialize crypto data for the input and output data */ 89 T_cd.cd_format = CRYPTO_DATA_RAW; 90 T_cd.cd_offset = 0; 91 T_cd.cd_raw.iov_base = (char *)T; 92 93 c_cd.cd_format = CRYPTO_DATA_RAW; 94 c_cd.cd_offset = 0; 95 c_cd.cd_length = 1; 96 c_cd.cd_raw.iov_base = (char *)&c; 97 c_cd.cd_raw.iov_len = c_cd.cd_length; 98 99 info_cd.cd_format = CRYPTO_DATA_RAW; 100 info_cd.cd_offset = 0; 101 info_cd.cd_length = info_len; 102 info_cd.cd_raw.iov_base = (char *)info; 103 info_cd.cd_raw.iov_len = info_cd.cd_length; 104 105 for (i = 1; i <= N; i++) { 106 c = i; 107 108 T_cd.cd_length = T_len; 109 T_cd.cd_raw.iov_len = T_cd.cd_length; 110 111 ret = crypto_mac_init(&mech, &key, NULL, &ctx); 112 if (ret != CRYPTO_SUCCESS) 113 return (SET_ERROR(EIO)); 114 115 ret = crypto_mac_update(ctx, &T_cd); 116 if (ret != CRYPTO_SUCCESS) 117 return (SET_ERROR(EIO)); 118 119 ret = crypto_mac_update(ctx, &info_cd); 120 if (ret != CRYPTO_SUCCESS) 121 return (SET_ERROR(EIO)); 122 123 ret = crypto_mac_update(ctx, &c_cd); 124 if (ret != CRYPTO_SUCCESS) 125 return (SET_ERROR(EIO)); 126 127 T_len = SHA512_DIGEST_LENGTH; 128 T_cd.cd_length = T_len; 129 T_cd.cd_raw.iov_len = T_cd.cd_length; 130 131 ret = crypto_mac_final(ctx, &T_cd); 132 if (ret != CRYPTO_SUCCESS) 133 return (SET_ERROR(EIO)); 134 135 memcpy(out_buf + pos, T, 136 (i != N) ? SHA512_DIGEST_LENGTH : (out_len - pos)); 137 pos += SHA512_DIGEST_LENGTH; 138 } 139 140 return (0); 141 } 142 143 /* 144 * HKDF is designed to be a relatively fast function for deriving keys from a 145 * master key + a salt. We use this function to generate new encryption keys 146 * so as to avoid hitting the cryptographic limits of the underlying 147 * encryption modes. Note that, for the sake of deriving encryption keys, the 148 * info parameter is called the "salt" everywhere else in the code. 149 */ 150 int 151 hkdf_sha512(uint8_t *key_material, uint_t km_len, uint8_t *salt, 152 uint_t salt_len, uint8_t *info, uint_t info_len, uint8_t *output_key, 153 uint_t out_len) 154 { 155 int ret; 156 uint8_t extract_key[SHA512_DIGEST_LENGTH]; 157 158 ret = hkdf_sha512_extract(salt, salt_len, key_material, km_len, 159 extract_key); 160 if (ret != 0) 161 return (ret); 162 163 ret = hkdf_sha512_expand(extract_key, info, info_len, output_key, 164 out_len); 165 if (ret != 0) 166 return (ret); 167 168 return (0); 169 } 170