<commit_before>#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#=======================================================================
#
# cmac.py
# ------
# Simple, pure Python, CMAC implementation using the
# word based model of the AES cipher withsupport for 128 and
# 256 bit keys.
#
# Test vectors used in the tests are from the NIST specification:
# http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf
#
#
#
# Author: <NAME>
# Copyright (c) 2016, Secworks Sweden AB
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#=======================================================================

#-------------------------------------------------------------------
# Python module imports.
#-------------------------------------------------------------------
import sys

# Note this assumes that the aes implementation is either in the
# same dir or symlinked.
from aes import *


#-------------------------------------------------------------------
# Constants.
#-------------------------------------------------------------------
VERBOSE = True
R128 = (0, 0, 0, 0x00000087)
MAX128 = ((2**128) - 1)


#-------------------------------------------------------------------
# check_block()
#
# Check and report if a result block matches expected block.
#-------------------------------------------------------------------
def check_block(expected, result):
    if (expected[0] == result[0]) and  (expected[1] == result[1]) and\
         (expected[2] == result[2]) and  (expected[3] == result[3]):
        print("OK. Result matches expected.")
    else:
        print("ERROR. Result does not match expected.")
        print("Expected:")
        print_block(expected)
        print("Got:")
        print_block(result)
        print("")


#-------------------------------------------------------------------
# xor_words()
#-------------------------------------------------------------------
def xor_words(a, b):
    c = (a[0] ^ b[0], a[1] ^ b[1], a[2] ^ b[2], a[3] ^ b[3])
    if VERBOSE:
        print("XORing words in the following two 128 bit block gives the result:")
        print_block(a)
        print_block(b)
        print_block(c)
    return c


#-------------------------------------------------------------------
# shift_words()
#-------------------------------------------------------------------
def shift_words(wl):
    w = ((wl[0] << 96) + (wl[1] << 64) + (wl[2] << 32) + wl[3]) & MAX128
    ws = w << 1 & MAX128
    return ((ws >> 96) & 0xffffffff, (ws >> 64) & 0xffffffff,
            (ws >> 32) & 0xffffffff, ws & 0xffffffff)


#-------------------------------------------------------------------
# pad_block()
#
# Pad a given block with the "1000...." paddning as given by the
# bitlen. Note that bitlen is assumed to be in the
# range [0..127]
#-------------------------------------------------------------------
def pad_block(block, bitlen):
    bw = ((block[0] << 96) + (block[1] << 64) + (block[2] << 32) + block[3]) & MAX128
    return block


#-------------------------------------------------------------------
# cmac_gen_subkeys()
#
# Generate subkeys K1 and K2.
#-------------------------------------------------------------------
def cmac_gen_subkeys(key):
    L = aes_encipher_block(key, (0, 0, 0, 0))

    Pre_K1 = shift_words(L)
    MSBL = (L[0] >> 31) & 0x01
    if MSBL:
        K1 = xor_words(Pre_K1, R128)
    else:
        K1 = Pre_K1


    Pre_K2 = shift_words(K1)
    MSBK1 = (K1[0] >> 31) & 0x01
    if MSBK1:
        K2 = xor_words(Pre_K2, R128)
    else:
        K2 = Pre_K2

    if VERBOSE:
        print("Internal data during sub key generation")<commit_msg>Completed first implementation of cmac padding.<commit_after>#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#=======================================================================
#
# cmac.py
# ------
# Simple, pure Python, CMAC implementation using the
# word based model of the AES cipher withsupport for 128 and
# 256 bit keys.
#
# Test vectors used in the tests are from the NIST specification:
# http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf
#
#
#
# Author: <NAME>
# Copyright (c) 2016, Secworks Sweden AB
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#=======================================================================

#-------------------------------------------------------------------
# Python module imports.
#-------------------------------------------------------------------
import sys

# Note this assumes that the aes implementation is either in the
# same dir or symlinked.
from aes import *


#-------------------------------------------------------------------
# Constants.
#-------------------------------------------------------------------
VERBOSE = True
R128 = (0, 0, 0, 0x00000087)
MAX128 = ((2**128) - 1)


#-------------------------------------------------------------------
# check_block()
#
# Check and report if a result block matches expected block.
#-------------------------------------------------------------------
def check_block(expected, result):
    if (expected[0] == result[0]) and  (expected[1] == result[1]) and\
         (expected[2] == result[2]) and  (expected[3] == result[3]):
        print("OK. Result matches expected.")
    else:
        print("ERROR. Result does not match expected.")
        print("Expected:")
        print_block(expected)
        print("Got:")
        print_block(result)
        print("")


#-------------------------------------------------------------------
# xor_words()
#-------------------------------------------------------------------
def xor_words(a, b):
    c = (a[0] ^ b[0], a[1] ^ b[1], a[2] ^ b[2], a[3] ^ b[3])
    if VERBOSE:
        print("XORing words in the following two 128 bit block gives the result:")
        print_block(a)
        print_block(b)
        print_block(c)
    return c


#-------------------------------------------------------------------
# shift_words()
#-------------------------------------------------------------------
def shift_words(wl):
    w = ((wl[0] << 96) + (wl[1] << 64) + (wl[2] << 32) + wl[3]) & MAX128
    ws = w << 1 & MAX128
    return ((ws >> 96) & 0xffffffff, (ws >> 64) & 0xffffffff,
            (ws >> 32) & 0xffffffff, ws & 0xffffffff)


#-------------------------------------------------------------------
# pad_block()
#
# Pad a given block with the "1000...." paddning as given by the
# bitlen. Note that bitlen is assumed to be in the
# range [0..127]
#-------------------------------------------------------------------
def pad_block(block, bitlen):
    bw = ((block[0] << 96) + (block[1] << 64) + (block[2] << 32) + block[3]) & MAX128
    bitstr = "1" * bitlen + "1" + "0" * (127 - bitlen)
    bitmask = int(bitstr, 2)
    padded = bw & bitmask
    pblock = ((padded >> 96) & 0xffffffff, (padded >> 64) & 0xffffffff,
              (padded >> 32) & 0xffffffff, padded & 0xffffffff)
    return pblock


#-------------------------------------------------------------------
# cmac_gen_subkeys()
#
# Generate subkeys K1 and K2.
#-------------------------------------------------------------------
def cmac_gen_subkeys(key):
    L = aes_encipher_block(key, (0, 0, 0, 0))

    Pre_K1 = shift_words(L)
    MSBL = (L[0] >> 31) & 0x01
    if MSBL:
        K1 = xor_words(Pre_K1, R128)
    else:
        K1 = Pre_K1


    Pre_K2 = shift_words(K1)
    MSBK1 = (K1[0] >> 31) & 0x01
    if MSBK1:
        K2 = xor_words(Pre_K2, R128)
    else:
        K2 = Pre_K2

    if VERBOSE:
        print("Internal data during sub key generation")
{'fraction_non_alphanumeric': 0.30852651477464926, 'fraction_numerical': 0.02994726892846483, 'mean_word_length': 1.6719829877724615, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 12, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5253061', 'n_tokens_mistral': 2952, 'n_tokens_neox': 2584, 'n_words': 947}