]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
libcli/smb: split out smb2_signing_calc_signature() from smb2_signing_check_pdu()
authorStefan Metzmacher <metze@samba.org>
Wed, 11 Nov 2020 12:00:34 +0000 (13:00 +0100)
committerJeremy Allison <jra@samba.org>
Wed, 17 Mar 2021 00:49:32 +0000 (00:49 +0000)
We only need one function to calculate the signature of an SMB2 packet.
And that only need the logic based on a gnutls_mac_algorithm_t once.

The next step will convert smb2_signing_sign_pdu() to also use
smb2_signing_calc_signature(). Doing that in a separate commit
should make sure we don't introduce a symetric bug.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14512

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
libcli/smb/smb2_constants.h
libcli/smb/smb2_signing.c

index ea1a21c84e84453d1c0da455572f383875f25e67..64d5ec697cbf1f7ad7b8ebaeeab339c128f084ca 100644 (file)
 /* Values for the SMB2_PREAUTH_INTEGRITY_CAPABILITIES Context (>= 0x310) */
 #define SMB2_PREAUTH_INTEGRITY_SHA512       0x0001
 
+#define SMB2_SIGNING_INVALID_ALGO          0xffff /* only used internally */
+#define SMB2_SIGNING_HMAC_SHA256           0x0000 /* default <= 0x210 */
+#define SMB2_SIGNING_AES128_CMAC           0x0001 /* default >= 0x224 */
+
 /* Values for the SMB2_ENCRYPTION_CAPABILITIES Context (>= 0x310) */
 #define SMB2_ENCRYPTION_AES128_CCM         0x0001 /* only in dialect >= 0x224 */
 #define SMB2_ENCRYPTION_AES128_GCM         0x0002 /* only in dialect >= 0x310 */
index 5927a1331ac71fc5d875de4aafee4a13088bf0b9..6da289dc4342174d817e08a8119cdad7f3a1079b 100644 (file)
@@ -62,6 +62,105 @@ bool smb2_signing_key_valid(const struct smb2_signing_key *key)
        return true;
 }
 
+static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key,
+                                           uint16_t sign_algo_id,
+                                           const struct iovec *vector,
+                                           int count,
+                                           uint8_t signature[16])
+{
+       const uint8_t *hdr = (uint8_t *)vector[0].iov_base;
+       static const uint8_t zero_sig[16] = { 0, };
+       gnutls_mac_algorithm_t hmac_algo = GNUTLS_MAC_UNKNOWN;
+       int i;
+
+       SMB_ASSERT(count >= 2);
+       SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
+
+       switch (sign_algo_id) {
+       case SMB2_SIGNING_AES128_CMAC:
+#ifdef HAVE_GNUTLS_AES_CMAC
+               hmac_algo = GNUTLS_MAC_AES_CMAC_128;
+               break;
+#else /* NOT HAVE_GNUTLS_AES_CMAC */
+       {
+               struct aes_cmac_128_context ctx;
+               uint8_t key[AES_BLOCK_SIZE] = {0};
+
+               memcpy(key,
+                      signing_key->blob.data,
+                      MIN(signing_key->blob.length, 16));
+
+               aes_cmac_128_init(&ctx, key);
+               aes_cmac_128_update(&ctx, hdr, SMB2_HDR_SIGNATURE);
+               aes_cmac_128_update(&ctx, zero_sig, 16);
+               for (i=1; i < count; i++) {
+                       aes_cmac_128_update(&ctx,
+                                       (const uint8_t *)vector[i].iov_base,
+                                       vector[i].iov_len);
+               }
+               aes_cmac_128_final(&ctx, signature);
+
+               ZERO_ARRAY(key);
+
+               return NT_STATUS_OK;
+       }       break;
+#endif
+       case SMB2_SIGNING_HMAC_SHA256:
+               hmac_algo = GNUTLS_MAC_SHA256;
+               break;
+
+       default:
+               return NT_STATUS_HMAC_NOT_SUPPORTED;
+       }
+
+       if (hmac_algo != GNUTLS_MAC_UNKNOWN) {
+               uint8_t digest[gnutls_hash_get_len(hmac_algo)];
+               gnutls_datum_t key = {
+                       .data = signing_key->blob.data,
+                       .size = MIN(signing_key->blob.length, 16),
+               };
+               int rc;
+
+               if (signing_key->hmac_hnd == NULL) {
+                       rc = gnutls_hmac_init(&signing_key->hmac_hnd,
+                                             hmac_algo,
+                                             key.data,
+                                             key.size);
+                       if (rc < 0) {
+                               return gnutls_error_to_ntstatus(rc,
+                                               NT_STATUS_HMAC_NOT_SUPPORTED);
+                       }
+               }
+
+               rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
+               if (rc < 0) {
+                       return gnutls_error_to_ntstatus(rc,
+                                               NT_STATUS_HMAC_NOT_SUPPORTED);
+               }
+               rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
+               if (rc < 0) {
+                       return gnutls_error_to_ntstatus(rc,
+                                               NT_STATUS_HMAC_NOT_SUPPORTED);
+               }
+
+               for (i = 1; i < count; i++) {
+                       rc = gnutls_hmac(signing_key->hmac_hnd,
+                                        vector[i].iov_base,
+                                        vector[i].iov_len);
+                       if (rc < 0) {
+                               return gnutls_error_to_ntstatus(rc,
+                                               NT_STATUS_HMAC_NOT_SUPPORTED);
+                       }
+               }
+               gnutls_hmac_output(signing_key->hmac_hnd, digest);
+               memcpy(signature, digest, 16);
+               ZERO_ARRAY(digest);
+               return NT_STATUS_OK;
+       }
+
+       return NT_STATUS_HMAC_NOT_SUPPORTED;
+}
+
 NTSTATUS smb2_signing_sign_pdu(struct smb2_signing_key *signing_key,
                               enum protocol_types protocol,
                               struct iovec *vector,
@@ -182,12 +281,12 @@ NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
                                const struct iovec *vector,
                                int count)
 {
+       uint16_t sign_algo_id;
        const uint8_t *hdr;
        const uint8_t *sig;
        uint64_t session_id;
        uint8_t res[16];
-       static const uint8_t zero_sig[16] = { 0, };
-       int i;
+       NTSTATUS status;
 
        SMB_ASSERT(count >= 2);
        SMB_ASSERT(vector[0].iov_len == SMB2_HDR_BODY);
@@ -211,100 +310,25 @@ NTSTATUS smb2_signing_check_pdu(struct smb2_signing_key *signing_key,
        sig = hdr+SMB2_HDR_SIGNATURE;
 
        if (protocol >= PROTOCOL_SMB2_24) {
-#ifdef HAVE_GNUTLS_AES_CMAC
-               gnutls_datum_t key = {
-                       .data = signing_key->blob.data,
-                       .size = MIN(signing_key->blob.length, 16),
-               };
-               int rc;
-
-               if (signing_key->hmac_hnd == NULL) {
-                       rc = gnutls_hmac_init(&signing_key->hmac_hnd,
-                                             GNUTLS_MAC_AES_CMAC_128,
-                                             key.data,
-                                             key.size);
-                       if (rc < 0) {
-                               return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
-                       }
-               }
-
-               rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
-               if (rc < 0) {
-                       return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
-               }
-
-               rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
-               if (rc < 0) {
-                       return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
-               }
-
-               for (i = 1; i < count; i++) {
-                       rc = gnutls_hmac(signing_key->hmac_hnd,
-                                        vector[i].iov_base,
-                                        vector[i].iov_len);
-                       if (rc < 0) {
-                               return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
-                       }
-               }
-               gnutls_hmac_output(signing_key->hmac_hnd, res);
-#else /* NOT HAVE_GNUTLS_AES_CMAC */
-               struct aes_cmac_128_context ctx;
-               uint8_t key[AES_BLOCK_SIZE] = {0};
-
-               memcpy(key,
-                      signing_key->blob.data,
-                      MIN(signing_key->blob.length, 16));
-
-               aes_cmac_128_init(&ctx, key);
-               aes_cmac_128_update(&ctx, hdr, SMB2_HDR_SIGNATURE);
-               aes_cmac_128_update(&ctx, zero_sig, 16);
-               for (i=1; i < count; i++) {
-                       aes_cmac_128_update(&ctx,
-                                       (const uint8_t *)vector[i].iov_base,
-                                       vector[i].iov_len);
-               }
-               aes_cmac_128_final(&ctx, res);
-
-               ZERO_ARRAY(key);
-#endif
+               sign_algo_id = SMB2_SIGNING_AES128_CMAC;
        } else {
-               uint8_t digest[gnutls_hash_get_len(GNUTLS_MAC_SHA256)];
-               int rc;
-
-               if (signing_key->hmac_hnd == NULL) {
-                       rc = gnutls_hmac_init(&signing_key->hmac_hnd,
-                                             GNUTLS_MAC_SHA256,
-                                             signing_key->blob.data,
-                                             MIN(signing_key->blob.length, 16));
-                       if (rc < 0) {
-                               return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
-                       }
-               }
-
-               rc = gnutls_hmac(signing_key->hmac_hnd, hdr, SMB2_HDR_SIGNATURE);
-               if (rc < 0) {
-                       return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
-               }
-               rc = gnutls_hmac(signing_key->hmac_hnd, zero_sig, 16);
-               if (rc < 0) {
-                       return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
-               }
+               sign_algo_id = SMB2_SIGNING_HMAC_SHA256;
+       }
 
-               for (i = 1; i < count; i++) {
-                       rc = gnutls_hmac(signing_key->hmac_hnd,
-                                        vector[i].iov_base,
-                                        vector[i].iov_len);
-                       if (rc < 0) {
-                               return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
-                       }
-               }
-               gnutls_hmac_output(signing_key->hmac_hnd, digest);
-               memcpy(res, digest, 16);
-               ZERO_ARRAY(digest);
+       status = smb2_signing_calc_signature(signing_key,
+                                            sign_algo_id,
+                                            vector,
+                                            count,
+                                            res);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_ERR("smb2_signing_calc_signature(sign_algo_id=%u) - %s\n",
+                       (unsigned)sign_algo_id, nt_errstr(status));
+               return status;
        }
 
        if (memcmp_const_time(res, sig, 16) != 0) {
-               DEBUG(0,("Bad SMB2 signature for message\n"));
+               DEBUG(0,("Bad SMB2 (sign_algo_id=%u) signature for message\n",
+                        (unsigned)sign_algo_id));
                dump_data(0, sig, 16);
                dump_data(0, res, 16);
                return NT_STATUS_ACCESS_DENIED;