1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 14 */ 15 16 /* 17 * Helper functions for SMB signing using PKCS#11 18 * 19 * There are two implementations of these functions: 20 * This one (for user space) and another for kernel. 21 * See: uts/common/fs/smbclnt/netsmb/smb_sign_kcf.c 22 */ 23 24 #include <stdlib.h> 25 #include <strings.h> 26 #include <netsmb/smb_signing.h> 27 #include <security/cryptoki.h> 28 #include <security/pkcs11.h> 29 30 /* 31 * SMB1 signing helpers: 32 * (getmech, init, update, final) 33 */ 34 35 int 36 smb_md5_getmech(smb_sign_mech_t *mech) 37 { 38 mech->mechanism = CKM_MD5; 39 mech->pParameter = NULL; 40 mech->ulParameterLen = 0; 41 return (0); 42 } 43 44 /* 45 * Start PKCS#11 session. 46 */ 47 int 48 smb_md5_init(smb_sign_ctx_t *ctxp, smb_sign_mech_t *mech) 49 { 50 CK_RV rv; 51 52 rv = SUNW_C_GetMechSession(mech->mechanism, ctxp); 53 if (rv != CKR_OK) 54 return (-1); 55 56 rv = C_DigestInit(*ctxp, mech); 57 58 return (rv == CKR_OK ? 0 : -1); 59 } 60 61 /* 62 * Digest one segment 63 */ 64 int 65 smb_md5_update(smb_sign_ctx_t ctx, void *buf, size_t len) 66 { 67 CK_RV rv; 68 69 rv = C_DigestUpdate(ctx, buf, len); 70 if (rv != CKR_OK) 71 (void) C_CloseSession(ctx); 72 73 return (rv == CKR_OK ? 0 : -1); 74 } 75 76 /* 77 * Get the final digest. 78 */ 79 int 80 smb_md5_final(smb_sign_ctx_t ctx, uint8_t *digest16) 81 { 82 CK_ULONG len = MD5_DIGEST_LENGTH; 83 CK_RV rv; 84 85 rv = C_DigestFinal(ctx, digest16, &len); 86 (void) C_CloseSession(ctx); 87 88 return (rv == CKR_OK ? 0 : -1); 89 } 90 91 /* 92 * SMB2 signing helpers: 93 * (getmech, init, update, final) 94 */ 95 96 int 97 smb2_hmac_getmech(smb_sign_mech_t *mech) 98 { 99 mech->mechanism = CKM_SHA256_HMAC; 100 mech->pParameter = NULL; 101 mech->ulParameterLen = 0; 102 return (0); 103 } 104 105 /* 106 * Start PKCS#11 session, load the key. 107 */ 108 int 109 smb2_hmac_init(smb_sign_ctx_t *ctxp, smb_sign_mech_t *mech, 110 uint8_t *key, size_t key_len) 111 { 112 CK_OBJECT_HANDLE hkey = 0; 113 CK_RV rv; 114 115 rv = SUNW_C_GetMechSession(mech->mechanism, ctxp); 116 if (rv != CKR_OK) 117 return (-1); 118 119 rv = SUNW_C_KeyToObject(*ctxp, mech->mechanism, 120 key, key_len, &hkey); 121 if (rv != CKR_OK) 122 return (-1); 123 124 rv = C_SignInit(*ctxp, mech, hkey); 125 (void) C_DestroyObject(*ctxp, hkey); 126 127 return (rv == CKR_OK ? 0 : -1); 128 } 129 130 /* 131 * Digest one segment 132 */ 133 int 134 smb2_hmac_update(smb_sign_ctx_t ctx, uint8_t *in, size_t len) 135 { 136 CK_RV rv; 137 138 rv = C_SignUpdate(ctx, in, len); 139 if (rv != CKR_OK) 140 (void) C_CloseSession(ctx); 141 142 return (rv == CKR_OK ? 0 : -1); 143 } 144 145 /* 146 * Note, the SMB2 signature is the first 16 bytes of the 147 * 32-byte SHA256 HMAC digest. 148 */ 149 int 150 smb2_hmac_final(smb_sign_ctx_t ctx, uint8_t *digest16) 151 { 152 uint8_t full_digest[SHA256_DIGEST_LENGTH]; 153 CK_ULONG len = SHA256_DIGEST_LENGTH; 154 CK_RV rv; 155 156 rv = C_SignFinal(ctx, full_digest, &len); 157 if (rv == CKR_OK) 158 bcopy(full_digest, digest16, 16); 159 160 (void) C_CloseSession(ctx); 161 162 return (rv == CKR_OK ? 0 : -1); 163 } 164