[aes/model] Add example to test CBC and CTR modes
Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
diff --git a/hw/ip/aes/model/.gitignore b/hw/ip/aes/model/.gitignore
index eff2205..54ca492 100644
--- a/hw/ip/aes/model/.gitignore
+++ b/hw/ip/aes/model/.gitignore
@@ -1 +1,2 @@
aes_example
+aes_modes
diff --git a/hw/ip/aes/model/Makefile b/hw/ip/aes/model/Makefile
index 384c549..c7c1423 100644
--- a/hw/ip/aes/model/Makefile
+++ b/hw/ip/aes/model/Makefile
@@ -1,6 +1,6 @@
BORING_SSL_PATH=../boringssl
-NAME=aes_example
+NAME=aes_example aes_modes
FLAGS=-Wall -O2 -g
ifneq ($(wildcard $(BORING_SSL_PATH)/build/crypto/libcrypto.a),)
@@ -8,7 +8,9 @@
endif
all:
- gcc $(FLAGS) crypto.c aes.c $(NAME).c -o $(NAME) -I$(BORING_SSL_PATH) -L$(BORING_SSL_PATH)/build/crypto -lcrypto -lpthread
+ @for f in $(NAME) ; do \
+ gcc $(FLAGS) crypto.c aes.c $${f}.c -o $${f} -I$(BORING_SSL_PATH) -L$(BORING_SSL_PATH)/build/crypto -lcrypto -lpthread ; \
+ done
clean:
rm -f $(NAME)
diff --git a/hw/ip/aes/model/README.md b/hw/ip/aes/model/README.md
index 4968b6c..de36f64 100644
--- a/hw/ip/aes/model/README.md
+++ b/hw/ip/aes/model/README.md
@@ -1,42 +1,57 @@
-AES Model
-=========
+AES Model & OpenSSL/BoringSSL Interface
+=======================================
-This directory contains a basic C model of the AES unit targeting functional
-verfication of the AES unit during the design phase as well as later design
-verification.
+This directory contains a basic C model of the AES unit's cipher core including
+OpenSSL/BoringSSL library interface functions. This infrastructure targets
+functional verification of the AES unit during the design phase as well as
+actual design verification.
-Besides the actual model, this directory also contains an example application
-that:
-- Shows how to interface the C model.
-- Allows printing of intermediate results for debugging.
-- Checks the output of the model versus the exptected results.
+In addition, this directory also contains two example applications.
+
+1. `aes_example`:
+- Allows printing of intermediate results for debugging the AES cipher core.
+- Shows how to interface the C model and how to use the OpenSSL/BoringSSL
+ interface.
+- Checks the output of the model versus the expected results.
- Checks the output of the model versus the output of the BoringSSL/OpenSSL
library.
+- Supports ECB mode only.
-How to build and run the example
---------------------------------
+2. `aes_modes`:
+- Shows how to interface the OpenSSL/BoringSSL interface functions.
+- Checks the output of BoringSSL/OpenSSL versus expected results.
+- Supports ECB, CBC, CTR modes.
+
+How to build and run the examples
+---------------------------------
Open the makefile and update the variable BORING_SSL_PATH pointing to the
-BoringSSL directory on your machine. If make cannot find the crypto library
-in that directory, the example is automatically linked to OpenSSL instead
-of BoringSSL.
+BoringSSL directory on your machine. If make cannot find the crypto library in
+that directory, the example is automatically linked to OpenSSL instead of
+BoringSSL.
Simply execute
```make```
-to build the example and
+to build both example applications and
```./aes_example KEY_LEN_BYTES```
-to run the example. The optional argument KEY_LEN_BYTES determines the key
+to run `aes_example`. The optional argument `KEY_LEN_BYTES` determines the key
length in bytes and is either 16, 24, or 32 for AES-128, 192 or 256,
respectively. By default, a key length of 16 Bytes is used (AES-128).
+To run the second example, simply type
+
+ ```./aes_modes```
+
Details of the model
--------------------
-- aes.c/h: contains the C model of the AES unit
-- crypto.c/h: contains BoringSSL/OpenSSL library interface functions
-- aes_example.c/h: contains the example application including test
- input and expected output
+- `aes.c/h`: Contains the C model of the AES unit's cipher core.
+- `crypto.c/h`: Contains BoringSSL/OpenSSL library interface functions.
+- `aes_example.c/h`: Contains the first example application including test input
+ and expected output for ECB mode.
+- `aes_modes.c/h`: Contains the second example application including test input
+ and expected output for ECB, CBC, CTR modes.
diff --git a/hw/ip/aes/model/aes_modes.c b/hw/ip/aes/model/aes_modes.c
new file mode 100644
index 0000000..aa5a567
--- /dev/null
+++ b/hw/ip/aes/model/aes_modes.c
@@ -0,0 +1,220 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "aes.h"
+#include "aes_modes.h"
+
+#include "crypto.h"
+
+#ifdef USE_BORING_SSL
+char crypto_lib[10] = "BoringSSL";
+#else
+char crypto_lib[10] = "OpenSSL";
+#endif
+
+static int check_block(const unsigned char *actual,
+ const unsigned char *expected, const int print) {
+ for (int i = 0; i < 16; i++) {
+ if (actual[i] != expected[i]) {
+ if (print) {
+ printf("ERROR: block mismatch. Found %#x, expected %#x\n", actual[i],
+ expected[i]);
+ }
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int crypto_compare(const unsigned char *cipher_text,
+ const unsigned char *iv,
+ const unsigned char *plain_text, int len,
+ const unsigned char *key, int key_len,
+ crypto_mode_t mode) {
+ const unsigned char *data_in;
+ int ret_len;
+ int ret_len_exp = len;
+
+ // Enc
+ unsigned char *data_out =
+ (unsigned char *)malloc(ret_len_exp * sizeof(unsigned char));
+ if (data_out == NULL) {
+ printf("ERROR: malloc() failed\n");
+ return 1;
+ }
+ data_in = plain_text;
+
+ ret_len = crypto_encrypt(data_out, iv, data_in, len, key, key_len, mode);
+ if (ret_len != ret_len_exp) {
+ printf("ERROR: ret_len = %i, expected %i. Aborting now\n", ret_len,
+ ret_len_exp);
+ return 1;
+ }
+
+ for (int j = 0; j < len / 16; ++j) {
+ if (!check_block(&data_out[j * 16], &cipher_text[j * 16], 1)) {
+ printf("SUCCESS: %s encrypt output matches NIST example cipher text\n",
+ crypto_lib);
+ } else {
+ printf(
+ "ERROR: %s encrypt output does not match NIST example cipher text\n",
+ crypto_lib);
+ printf("Input: \t\t");
+ aes_print_block(&data_in[j * 16], 16);
+ printf("Output: \t");
+ aes_print_block(&data_out[j * 16], 16);
+ printf("Expected: \t");
+ aes_print_block(&cipher_text[j * 16], 16);
+ return 1;
+ }
+ }
+
+ // Dec
+ unsigned char *data_in_dec =
+ (unsigned char *)malloc(ret_len_exp * sizeof(unsigned char));
+ if (data_in_dec == NULL) {
+ printf("ERROR: malloc() failed\n");
+ return 1;
+ }
+ for (int j = 0; j < ret_len; ++j) {
+ data_in_dec[j] = data_out[j];
+ }
+
+ ret_len =
+ crypto_decrypt(data_out, iv, data_in_dec, ret_len, key, key_len, mode);
+ if (ret_len != len) {
+ printf("ERROR: ret_len = %i, expected %i. Aborting now\n", ret_len, len);
+ return 1;
+ }
+
+ for (int j = 0; j < len / 16; ++j) {
+ if (!check_block(&data_out[j * 16], &plain_text[j * 16], 1)) {
+ printf("SUCCESS: %s decrypt output matches NIST example plain text\n",
+ crypto_lib);
+ } else {
+ printf(
+ "ERROR: %s decrypt output does not match NIST example plain text\n",
+ crypto_lib);
+ printf("Input: \t\t");
+ aes_print_block(&data_in_dec[j * 16], 16);
+ printf("Output: \t");
+ aes_print_block(&data_out[j * 16], 16);
+ printf("Expected: \t");
+ aes_print_block(&plain_text[j * 16], 16);
+ return 1;
+ }
+ }
+
+ free(data_out);
+ free(data_in_dec);
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ const int len = 64;
+ int key_len;
+ crypto_mode_t mode;
+ const unsigned char *iv;
+ const unsigned char *key;
+ const unsigned char *cipher_text;
+
+ /////////
+ // ECB //
+ /////////
+ iv = aes_modes_iv_ecb;
+ mode = kCryptoAesEcb;
+
+ for (int i = 0; i < 3; ++i) {
+ if (i == 0) {
+ printf("ECB AES-128\n");
+ key_len = 16;
+ key = aes_modes_key_128;
+ cipher_text = aes_modes_cipher_text_ecb_128;
+ } else if (i == 1) {
+ printf("ECB AES-192\n");
+ key_len = 24;
+ key = aes_modes_key_192;
+ cipher_text = aes_modes_cipher_text_ecb_192;
+ } else { // i==2
+ printf("ECB AES-256\n");
+ key_len = 32;
+ key = aes_modes_key_256;
+ cipher_text = aes_modes_cipher_text_ecb_256;
+ }
+
+ if (crypto_compare(cipher_text, iv, aes_modes_plain_text, len, key, key_len,
+ mode)) {
+ return 1;
+ }
+ }
+
+ /////////
+ // CBC //
+ /////////
+ iv = aes_modes_iv_cbc;
+ mode = kCryptoAesCbc;
+
+ for (int i = 0; i < 3; ++i) {
+ if (i == 0) {
+ printf("CBC AES-128\n");
+ key_len = 16;
+ key = aes_modes_key_128;
+ cipher_text = aes_modes_cipher_text_cbc_128;
+ } else if (i == 1) {
+ printf("CBC AES-192\n");
+ key_len = 24;
+ key = aes_modes_key_192;
+ cipher_text = aes_modes_cipher_text_cbc_192;
+ } else { // i==2
+ printf("CBC AES-256\n");
+ key_len = 32;
+ key = aes_modes_key_256;
+ cipher_text = aes_modes_cipher_text_cbc_256;
+ }
+
+ if (crypto_compare(cipher_text, iv, aes_modes_plain_text, len, key, key_len,
+ mode)) {
+ return 1;
+ }
+ }
+
+ /////////
+ // CTR //
+ /////////
+ iv = aes_modes_iv_ctr;
+ mode = kCryptoAesCtr;
+
+ for (int i = 0; i < 3; ++i) {
+ if (i == 0) {
+ printf("CTR AES-128\n");
+ key_len = 16;
+ key = aes_modes_key_128;
+ cipher_text = aes_modes_cipher_text_ctr_128;
+ } else if (i == 1) {
+ printf("CTR AES-192\n");
+ key_len = 24;
+ key = aes_modes_key_192;
+ cipher_text = aes_modes_cipher_text_ctr_192;
+ } else { // i==2
+ printf("CTR AES-256\n");
+ key_len = 32;
+ key = aes_modes_key_256;
+ cipher_text = aes_modes_cipher_text_ctr_256;
+ }
+
+ if (crypto_compare(cipher_text, iv, aes_modes_plain_text, len, key, key_len,
+ mode)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/hw/ip/aes/model/aes_modes.core b/hw/ip/aes/model/aes_modes.core
new file mode 100644
index 0000000..868f971
--- /dev/null
+++ b/hw/ip/aes/model/aes_modes.core
@@ -0,0 +1,23 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:model:aes_modes:0.5"
+description: "AES Modes"
+filesets:
+ files_dv:
+ files:
+ - aes_modes.h: { is_include_file: true }
+ file_type: cSource
+
+targets:
+ default:
+ filesets:
+ - files_dv
+
+ tools:
+ verilator:
+ mode: cc
+ verilator_options:
+# linker flags
+ - '-LDFLAGS "-pthread -lcrypto"'
diff --git a/hw/ip/aes/model/aes_modes.h b/hw/ip/aes/model/aes_modes.h
new file mode 100644
index 0000000..12f5c46
--- /dev/null
+++ b/hw/ip/aes/model/aes_modes.h
@@ -0,0 +1,112 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// The examples below are extracted from the NIST Publication SP 800-38A
+// "Recommendation for Block Cipher Modes of Operation: Methods and Techniques"
+// available at https://csrc.nist.gov/publications/detail/sp/800-38a/final .
+
+static const unsigned char aes_modes_plain_text[64] = {
+ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e,
+ 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03,
+ 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30,
+ 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19,
+ 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b,
+ 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10};
+
+static const unsigned char aes_modes_key_128[16] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
+
+static const unsigned char aes_modes_key_192[24] = {
+ 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b,
+ 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b};
+
+static const unsigned char aes_modes_key_256[32] = {
+ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae,
+ 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61,
+ 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4};
+
+static const unsigned char aes_modes_iv_ecb[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+static const unsigned char aes_modes_cipher_text_ecb_128[64] = {
+ 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, 0xa8, 0x9e, 0xca,
+ 0xf3, 0x24, 0x66, 0xef, 0x97, 0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9,
+ 0x69, 0x9d, 0xe7, 0x85, 0x89, 0x5a, 0x96, 0xfd, 0xba, 0xaf, 0x43,
+ 0xb1, 0xcd, 0x7f, 0x59, 0x8e, 0xce, 0x23, 0x88, 0x1b, 0x00, 0xe3,
+ 0xed, 0x03, 0x06, 0x88, 0x7b, 0x0c, 0x78, 0x5e, 0x27, 0xe8, 0xad,
+ 0x3f, 0x82, 0x23, 0x20, 0x71, 0x04, 0x72, 0x5d, 0xd4};
+
+static const unsigned char aes_modes_cipher_text_ecb_192[64] = {
+ 0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f, 0xf7, 0x12, 0xa2,
+ 0x14, 0x57, 0x1f, 0xa5, 0xcc, 0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a,
+ 0xd3, 0xad, 0x77, 0x34, 0xec, 0xb3, 0xec, 0xee, 0x4e, 0xef, 0xef,
+ 0x7a, 0xfd, 0x22, 0x70, 0xe2, 0xe6, 0x0a, 0xdc, 0xe0, 0xba, 0x2f,
+ 0xac, 0xe6, 0x44, 0x4e, 0x9a, 0x4b, 0x41, 0xba, 0x73, 0x8d, 0x6c,
+ 0x72, 0xfb, 0x16, 0x69, 0x16, 0x03, 0xc1, 0x8e, 0x0e};
+
+static const unsigned char aes_modes_cipher_text_ecb_256[64] = {
+ 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, 0x06, 0x4b, 0x5a,
+ 0x7e, 0x3d, 0xb1, 0x81, 0xf8, 0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10,
+ 0xed, 0x26, 0xdc, 0x5b, 0xa7, 0x4a, 0x31, 0x36, 0x28, 0x70, 0xb6,
+ 0xed, 0x21, 0xb9, 0x9c, 0xa6, 0xf4, 0xf9, 0xf1, 0x53, 0xe7, 0xb1,
+ 0xbe, 0xaf, 0xed, 0x1d, 0x23, 0x30, 0x4b, 0x7a, 0x39, 0xf9, 0xf3,
+ 0xff, 0x06, 0x7d, 0x8d, 0x8f, 0x9e, 0x24, 0xec, 0xc7};
+
+static const unsigned char aes_modes_iv_cbc[16] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
+
+static const unsigned char aes_modes_cipher_text_cbc_128[64] = {
+ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e,
+ 0x9b, 0x12, 0xe9, 0x19, 0x7d, 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72,
+ 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, 0x73,
+ 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e,
+ 0x22, 0x22, 0x95, 0x16, 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac,
+ 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7};
+
+static const unsigned char aes_modes_cipher_text_cbc_192[64] = {
+ 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18,
+ 0x3a, 0x9f, 0xa0, 0x71, 0xe8, 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d,
+ 0xed, 0xf4, 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a, 0x57,
+ 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0, 0x7f, 0xa9, 0xba, 0xac,
+ 0x3d, 0xf1, 0x02, 0xe0, 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88,
+ 0x81, 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd};
+
+static const unsigned char aes_modes_cipher_text_cbc_256[64] = {
+ 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab,
+ 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb,
+ 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d, 0x39,
+ 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63,
+ 0x04, 0x23, 0x14, 0x61, 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9,
+ 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b};
+
+static const unsigned char aes_modes_iv_ctr[16] = {
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff};
+
+static const unsigned char aes_modes_cipher_text_ctr_128[64] = {
+ 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68,
+ 0x64, 0x99, 0x0d, 0xb6, 0xce, 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70,
+ 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, 0x5a,
+ 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02,
+ 0x0d, 0xb0, 0x3e, 0xab, 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03,
+ 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee};
+
+static const unsigned char aes_modes_cipher_text_ctr_192[64] = {
+ 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, 0x4f, 0x2b, 0x04,
+ 0x59, 0xfe, 0x7e, 0x6e, 0x0b, 0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6,
+ 0xfa, 0xef, 0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94, 0x1e,
+ 0x36, 0xb2, 0x6b, 0xd1, 0xeb, 0xc6, 0x70, 0xd1, 0xbd, 0x1d, 0x66,
+ 0x56, 0x20, 0xab, 0xf7, 0x4f, 0x78, 0xa7, 0xf6, 0xd2, 0x98, 0x09,
+ 0x58, 0x5a, 0x97, 0xda, 0xec, 0x58, 0xc6, 0xb0, 0x50};
+
+static const unsigned char aes_modes_cipher_text_ctr_256[64] = {
+ 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, 0xb7, 0xa7, 0xf5,
+ 0x04, 0xbb, 0xf3, 0xd2, 0x28, 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62,
+ 0xb5, 0x9a, 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5, 0x2b,
+ 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c, 0xe8, 0x70, 0x17, 0xba,
+ 0x2d, 0x84, 0x98, 0x8d, 0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad,
+ 0xa6, 0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6};