• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 
16 #include "hitls_build.h"
17 #ifdef HITLS_CRYPTO_CMAC
18 
19 #include <stdlib.h>
20 #include "bsl_sal.h"
21 #include "crypt_errno.h"
22 #include "crypt_utils.h"
23 #include "bsl_err_internal.h"
24 #include "cipher_mac_common.h"
25 #include "crypt_cmac.h"
26 #include "eal_mac_local.h"
27 
CRYPT_CMAC_NewCtx(CRYPT_MAC_AlgId id)28 CRYPT_CMAC_Ctx *CRYPT_CMAC_NewCtx(CRYPT_MAC_AlgId id)
29 {
30     int32_t ret;
31     EAL_MacMethLookup method = {0};
32     ret = EAL_MacFindMethod(id, &method);
33     if (ret != CRYPT_SUCCESS) {
34         return NULL;
35     }
36     CRYPT_CMAC_Ctx *ctx = BSL_SAL_Calloc(1, sizeof(CRYPT_CMAC_Ctx));
37     if (ctx == NULL) {
38         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
39         return NULL;
40     }
41     ret = CipherMacInitCtx(ctx, method.ciph);
42     if (ret != CRYPT_SUCCESS) {
43         BSL_SAL_Free(ctx);
44         return NULL;
45     }
46     return ctx;
47 }
48 
CRYPT_CMAC_Init(CRYPT_CMAC_Ctx * ctx,const uint8_t * key,uint32_t len,void * param)49 int32_t CRYPT_CMAC_Init(CRYPT_CMAC_Ctx *ctx, const uint8_t *key, uint32_t len, void *param)
50 {
51     (void)param;
52     return CipherMacInit((Cipher_MAC_Common_Ctx *)ctx, key, len);
53 }
54 
CRYPT_CMAC_Update(CRYPT_CMAC_Ctx * ctx,const uint8_t * in,uint32_t len)55 int32_t CRYPT_CMAC_Update(CRYPT_CMAC_Ctx *ctx, const uint8_t *in, uint32_t len)
56 {
57     return CipherMacUpdate((Cipher_MAC_Common_Ctx *)ctx, in, len);
58 }
59 
LeftShiftOneBit(const uint8_t * in,uint32_t len,uint8_t * out)60 static inline void LeftShiftOneBit(const uint8_t *in, uint32_t len, uint8_t *out)
61 {
62     uint32_t i = len - 1;
63 
64     out[i] = (in[i] << 1) | 0;
65     do {
66         i--;
67         out[i] = (in[i] << 1) | (in[i + 1] >> 7); // 7 is used to obtain the most significant bit of the 8-bit data.
68     } while (i != 0);
69 }
70 
CMAC_Final(CRYPT_CMAC_Ctx * ctx)71 static void CMAC_Final(CRYPT_CMAC_Ctx *ctx)
72 {
73     const uint8_t z[CIPHER_MAC_MAXBLOCKSIZE] = {0};
74     uint8_t rb;
75     uint8_t l[CIPHER_MAC_MAXBLOCKSIZE];
76     uint8_t k1[CIPHER_MAC_MAXBLOCKSIZE];
77     const EAL_SymMethod *method = ctx->method;
78     uint32_t blockSize = method->blockSize;
79     int32_t ret;
80 
81     ret = method->encryptBlock(ctx->key, z, l, blockSize);
82     if (ret != CRYPT_SUCCESS) {
83         BSL_ERR_PUSH_ERROR(ret);
84         return;
85     }
86     LeftShiftOneBit(l, blockSize, k1);
87 
88     if (blockSize == CIPHER_MAC_MAXBLOCKSIZE) {
89         rb = 0x87; /* When the AES algorithm is used and the blocksize is 128 bits, rb uses 0x87. */
90     } else {
91         rb = 0x1B; /* When the DES and TDES algorithms are used and blocksize is 64 bits, rb uses 0x1B. */
92     }
93     if ((l[0] & 0x80) != 0) {
94         k1[blockSize - 1] ^= rb;
95     }
96     uint32_t length = ctx->len;
97     if (length == blockSize) {  // When the message length is an integer multiple of blockSize, use K1
98         DATA_XOR(ctx->left, k1, ctx->left, blockSize);
99     } else {  // The message length is not an integer multiple of blockSize. Use K2 after padding.
100         /* padding */
101         ctx->left[length++] = 0x80;  // 0x80 indicates that the first bit of the data is added with 1.
102         while (length < blockSize) {
103             ctx->left[length++] = 0;
104         }
105 
106         uint8_t k2[CIPHER_MAC_MAXBLOCKSIZE];
107         LeftShiftOneBit(k1, blockSize, k2);
108         if ((k1[0] & 0x80) != 0) {
109             k2[blockSize - 1] ^= rb;
110         }
111         DATA_XOR(ctx->left, k2, ctx->left, blockSize);
112         ctx->len = blockSize;
113     }
114 }
115 
CRYPT_CMAC_Final(CRYPT_CMAC_Ctx * ctx,uint8_t * out,uint32_t * len)116 int32_t CRYPT_CMAC_Final(CRYPT_CMAC_Ctx *ctx, uint8_t *out, uint32_t *len)
117 {
118     if (ctx == NULL || ctx->method == NULL || len == NULL || out == NULL) {
119         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
120         return CRYPT_NULL_INPUT;
121     }
122     const EAL_SymMethod *method = ctx->method;
123     uint32_t blockSize = method->blockSize;
124     if (*len < blockSize) {
125         BSL_ERR_PUSH_ERROR(CRYPT_CMAC_OUT_BUFF_LEN_NOT_ENOUGH);
126         return CRYPT_CMAC_OUT_BUFF_LEN_NOT_ENOUGH;
127     }
128 
129     CMAC_Final(ctx);
130     DATA_XOR(ctx->left, ctx->data, ctx->left, blockSize);
131     int32_t ret = method->encryptBlock(ctx->key, ctx->left, out, blockSize);
132     if (ret != CRYPT_SUCCESS) {
133         BSL_ERR_PUSH_ERROR(ret);
134         return ret;
135     }
136     *len = blockSize;
137     return CRYPT_SUCCESS;
138 }
139 
CRYPT_CMAC_Reinit(CRYPT_CMAC_Ctx * ctx)140 void CRYPT_CMAC_Reinit(CRYPT_CMAC_Ctx *ctx)
141 {
142     CipherMacReinit((Cipher_MAC_Common_Ctx *)ctx);
143 }
144 
CRYPT_CMAC_Deinit(CRYPT_CMAC_Ctx * ctx)145 void CRYPT_CMAC_Deinit(CRYPT_CMAC_Ctx *ctx)
146 {
147     CipherMacDeinit((Cipher_MAC_Common_Ctx *)ctx);
148 }
149 
CRYPT_CMAC_Ctrl(CRYPT_CMAC_Ctx * ctx,uint32_t opt,void * val,uint32_t len)150 int32_t CRYPT_CMAC_Ctrl(CRYPT_CMAC_Ctx *ctx, uint32_t opt, void *val, uint32_t len)
151 {
152     if (ctx == NULL) {
153         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
154         return CRYPT_NULL_INPUT;
155     }
156     switch (opt) {
157         case CRYPT_CTRL_GET_MACLEN:
158             return CipherMacGetMacLen(ctx, val, len);
159         default:
160             break;
161     }
162     BSL_ERR_PUSH_ERROR(CRYPT_CMAC_ERR_UNSUPPORTED_CTRL_OPTION);
163     return CRYPT_CMAC_ERR_UNSUPPORTED_CTRL_OPTION;
164 }
165 
CRYPT_CMAC_FreeCtx(CRYPT_CMAC_Ctx * ctx)166 void CRYPT_CMAC_FreeCtx(CRYPT_CMAC_Ctx *ctx)
167 {
168     CipherMacDeinitCtx(ctx);
169     BSL_SAL_Free(ctx);
170 }
171 
172 #endif /* HITLS_CRYPTO_CMAC */
173