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
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.
13 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
17 * Helper functions for SMB signing using the
18 * Kernel Cryptographic Framework (KCF)
21 #include <sys/types.h>
23 #include <sys/crypto/api.h>
24 #include <smbsrv/smb_kproto.h>
25 #include <smbsrv/smb_signing.h>
28 * SMB1 signing helpers:
29 * (getmech, init, update, final)
33 smb_md5_getmech(smb_sign_mech_t
*mech
)
37 t
= crypto_mech2id(SUN_CKM_MD5
);
38 if (t
== CRYPTO_MECH_INVALID
)
45 * Start the KCF session, load the key
48 smb_md5_init(smb_sign_ctx_t
*ctxp
, smb_sign_mech_t
*mech
)
52 rv
= crypto_digest_init(mech
, ctxp
, NULL
);
54 return (rv
== CRYPTO_SUCCESS
? 0 : -1);
61 smb_md5_update(smb_sign_ctx_t ctx
, void *buf
, size_t len
)
66 bzero(&data
, sizeof (data
));
67 data
.cd_format
= CRYPTO_DATA_RAW
;
69 data
.cd_raw
.iov_base
= buf
;
70 data
.cd_raw
.iov_len
= len
;
72 rv
= crypto_digest_update(ctx
, &data
, 0);
74 return (rv
== CRYPTO_SUCCESS
? 0 : -1);
78 * Get the final digest.
81 smb_md5_final(smb_sign_ctx_t ctx
, uint8_t *digest16
)
86 bzero(&out
, sizeof (out
));
87 out
.cd_format
= CRYPTO_DATA_RAW
;
88 out
.cd_length
= MD5_DIGEST_LENGTH
;
89 out
.cd_raw
.iov_len
= MD5_DIGEST_LENGTH
;
90 out
.cd_raw
.iov_base
= (void *)digest16
;
92 rv
= crypto_digest_final(ctx
, &out
, 0);
94 return (rv
== CRYPTO_SUCCESS
? 0 : -1);
98 * SMB2 signing helpers:
99 * (getmech, init, update, final)
103 smb2_hmac_getmech(smb_sign_mech_t
*mech
)
105 crypto_mech_type_t t
;
107 t
= crypto_mech2id(SUN_CKM_SHA256_HMAC
);
108 if (t
== CRYPTO_MECH_INVALID
)
115 * Start the KCF session, load the key
118 smb2_hmac_init(smb_sign_ctx_t
*ctxp
, smb_sign_mech_t
*mech
,
119 uint8_t *key
, size_t key_len
)
124 bzero(&ckey
, sizeof (ckey
));
125 ckey
.ck_format
= CRYPTO_KEY_RAW
;
127 ckey
.ck_length
= key_len
* 8; /* in bits */
129 rv
= crypto_mac_init(mech
, &ckey
, NULL
, ctxp
, NULL
);
131 return (rv
== CRYPTO_SUCCESS
? 0 : -1);
138 smb2_hmac_update(smb_sign_ctx_t ctx
, uint8_t *in
, size_t len
)
143 bzero(&data
, sizeof (data
));
144 data
.cd_format
= CRYPTO_DATA_RAW
;
145 data
.cd_length
= len
;
146 data
.cd_raw
.iov_base
= (void *)in
;
147 data
.cd_raw
.iov_len
= len
;
149 rv
= crypto_mac_update(ctx
, &data
, 0);
151 return (rv
== CRYPTO_SUCCESS
? 0 : -1);
155 * Note, the SMB2 signature is the first 16 bytes of the
156 * 32-byte SHA256 HMAC digest.
159 smb2_hmac_final(smb_sign_ctx_t ctx
, uint8_t *digest16
)
161 uint8_t full_digest
[SHA256_DIGEST_LENGTH
];
165 bzero(&out
, sizeof (out
));
166 out
.cd_format
= CRYPTO_DATA_RAW
;
167 out
.cd_length
= SHA256_DIGEST_LENGTH
;
168 out
.cd_raw
.iov_len
= SHA256_DIGEST_LENGTH
;
169 out
.cd_raw
.iov_base
= (void *)full_digest
;
171 rv
= crypto_mac_final(ctx
, &out
, 0);
172 if (rv
== CRYPTO_SUCCESS
)
173 bcopy(full_digest
, digest16
, 16);
175 return (rv
== CRYPTO_SUCCESS
? 0 : -1);