1 /* $OpenBSD: softraid.c,v 1.1 2016/09/11 17:49:36 jsing Exp $ */ 2 3 /* 4 * Copyright (c) 2012 Joel Sing <jsing@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/queue.h> 21 22 #include <dev/biovar.h> 23 #include <dev/softraidvar.h> 24 25 #include <lib/libsa/hmac_sha1.h> 26 #include <lib/libsa/pkcs5_pbkdf2.h> 27 #include <lib/libsa/rijndael.h> 28 29 #include "stand.h" 30 #include "softraid.h" 31 32 #define RIJNDAEL128_BLOCK_LEN 16 33 #define PASSPHRASE_LENGTH 1024 34 35 #define SR_CRYPTO_KEYBLOCK_BYTES SR_CRYPTO_MAXKEYS * SR_CRYPTO_KEYBYTES 36 37 /* List of softraid volumes. */ 38 struct sr_boot_volume_head sr_volumes; 39 40 /* List of softraid keydisks. */ 41 struct sr_boot_keydisk_head sr_keydisks; 42 43 #ifdef DEBUG 44 void 45 printhex(const char *s, const u_int8_t *buf, size_t len) 46 { 47 u_int8_t n1, n2; 48 size_t i; 49 50 printf("%s: ", s); 51 for (i = 0; i < len; i++) { 52 n1 = buf[i] & 0x0f; 53 n2 = buf[i] >> 4; 54 printf("%c", n2 > 9 ? n2 + 'a' - 10 : n2 + '0'); 55 printf("%c", n1 > 9 ? n1 + 'a' - 10 : n1 + '0'); 56 } 57 printf("\n"); 58 } 59 #endif 60 61 void 62 sr_clear_keys(void) 63 { 64 struct sr_boot_volume *bv; 65 struct sr_boot_keydisk *kd; 66 67 SLIST_FOREACH(bv, &sr_volumes, sbv_link) { 68 if (bv->sbv_level != 'C') 69 continue; 70 if (bv->sbv_keys != NULL) { 71 explicit_bzero(bv->sbv_keys, SR_CRYPTO_KEYBLOCK_BYTES); 72 free(bv->sbv_keys, SR_CRYPTO_KEYBLOCK_BYTES); 73 bv->sbv_keys = NULL; 74 } 75 if (bv->sbv_maskkey != NULL) { 76 explicit_bzero(bv->sbv_maskkey, SR_CRYPTO_MAXKEYBYTES); 77 free(bv->sbv_maskkey, SR_CRYPTO_MAXKEYBYTES); 78 bv->sbv_maskkey = NULL; 79 } 80 } 81 SLIST_FOREACH(kd, &sr_keydisks, kd_link) { 82 explicit_bzero(kd, sizeof(*kd)); 83 free(kd, sizeof(*kd)); 84 } 85 } 86 87 void 88 sr_crypto_calculate_check_hmac_sha1(u_int8_t *maskkey, int maskkey_size, 89 u_int8_t *key, int key_size, u_char *check_digest) 90 { 91 u_int8_t check_key[SHA1_DIGEST_LENGTH]; 92 SHA1_CTX shactx; 93 94 explicit_bzero(check_key, sizeof(check_key)); 95 explicit_bzero(&shactx, sizeof(shactx)); 96 97 /* k = SHA1(mask_key) */ 98 SHA1Init(&shactx); 99 SHA1Update(&shactx, maskkey, maskkey_size); 100 SHA1Final(check_key, &shactx); 101 102 /* mac = HMAC_SHA1_k(unencrypted key) */ 103 hmac_sha1(key, key_size, check_key, sizeof(check_key), check_digest); 104 105 explicit_bzero(check_key, sizeof(check_key)); 106 explicit_bzero(&shactx, sizeof(shactx)); 107 } 108 109 int 110 sr_crypto_decrypt_keys(struct sr_boot_volume *bv) 111 { 112 struct sr_meta_crypto *cm; 113 struct sr_boot_keydisk *kd; 114 struct sr_meta_opt_item *omi; 115 struct sr_crypto_pbkdf *kdfhint; 116 struct sr_crypto_kdfinfo kdfinfo; 117 char passphrase[PASSPHRASE_LENGTH]; 118 u_int8_t digest[SHA1_DIGEST_LENGTH]; 119 u_int8_t *keys = NULL; 120 u_int8_t *kp, *cp; 121 rijndael_ctx ctx; 122 int rv = -1; 123 int c, i; 124 125 SLIST_FOREACH(omi, &bv->sbv_meta_opt, omi_link) 126 if (omi->omi_som->som_type == SR_OPT_CRYPTO) 127 break; 128 129 if (omi == NULL) { 130 printf("Crypto metadata not found!\n"); 131 goto done; 132 } 133 134 cm = (struct sr_meta_crypto *)omi->omi_som; 135 kdfhint = (struct sr_crypto_pbkdf *)&cm->scm_kdfhint; 136 137 switch (cm->scm_mask_alg) { 138 case SR_CRYPTOM_AES_ECB_256: 139 break; 140 default: 141 printf("unsupported encryption algorithm %u\n", 142 cm->scm_mask_alg); 143 goto done; 144 } 145 146 SLIST_FOREACH(kd, &sr_keydisks, kd_link) { 147 if (bcmp(&kd->kd_uuid, &bv->sbv_uuid, sizeof(kd->kd_uuid)) == 0) 148 break; 149 } 150 if (kd) { 151 bcopy(&kd->kd_key, &kdfinfo.maskkey, sizeof(kdfinfo.maskkey)); 152 } else { 153 printf("Passphrase: "); 154 for (i = 0; i < PASSPHRASE_LENGTH - 1; i++) { 155 c = cngetc(); 156 if (c == '\r' || c == '\n') 157 break; 158 else if (c == '\b') { 159 i = i > 0 ? i - 2 : -1; 160 continue; 161 } 162 passphrase[i] = (c & 0xff); 163 } 164 passphrase[i] = 0; 165 printf("\n"); 166 167 #ifdef DEBUG 168 printf("Got passphrase: %s with len %d\n", 169 passphrase, strlen(passphrase)); 170 #endif 171 172 if (pkcs5_pbkdf2(passphrase, strlen(passphrase), kdfhint->salt, 173 sizeof(kdfhint->salt), kdfinfo.maskkey, 174 sizeof(kdfinfo.maskkey), kdfhint->rounds) != 0) { 175 printf("pbkdf2 failed\n"); 176 goto done; 177 } 178 } 179 180 /* kdfinfo->maskkey now has key. */ 181 182 /* Decrypt disk keys. */ 183 keys = alloc(SR_CRYPTO_KEYBLOCK_BYTES); 184 bzero(keys, SR_CRYPTO_KEYBLOCK_BYTES); 185 186 if (rijndael_set_key(&ctx, kdfinfo.maskkey, 256) != 0) 187 goto done; 188 189 cp = (u_int8_t *)cm->scm_key; 190 kp = keys; 191 for (i = 0; i < SR_CRYPTO_KEYBLOCK_BYTES; i += RIJNDAEL128_BLOCK_LEN) 192 rijndael_decrypt(&ctx, (u_char *)(cp + i), (u_char *)(kp + i)); 193 194 /* Check that the key decrypted properly. */ 195 sr_crypto_calculate_check_hmac_sha1(kdfinfo.maskkey, 196 sizeof(kdfinfo.maskkey), keys, SR_CRYPTO_KEYBLOCK_BYTES, digest); 197 198 if (bcmp(digest, cm->chk_hmac_sha1.sch_mac, sizeof(digest))) { 199 printf("incorrect passphrase or keydisk\n"); 200 goto done; 201 } 202 203 /* Keys and keydisks will be cleared before boot and from _rtt. */ 204 bv->sbv_keys = keys; 205 bv->sbv_maskkey = alloc(sizeof(kdfinfo.maskkey)); 206 bcopy(&kdfinfo.maskkey, bv->sbv_maskkey, sizeof(kdfinfo.maskkey)); 207 208 rv = 0; 209 210 done: 211 explicit_bzero(passphrase, PASSPHRASE_LENGTH); 212 explicit_bzero(&kdfinfo, sizeof(kdfinfo)); 213 explicit_bzero(digest, sizeof(digest)); 214 215 if (keys != NULL && rv != 0) { 216 explicit_bzero(keys, SR_CRYPTO_KEYBLOCK_BYTES); 217 free(keys, SR_CRYPTO_KEYBLOCK_BYTES); 218 } 219 220 return (rv); 221 } 222