1 /*
2   chronyd/chronyc - Programs for keeping computer clocks accurate.
3 
4  **********************************************************************
5  * Copyright (C) Miroslav Lichvar  2019
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of version 2 of the GNU General Public License as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  *
20  **********************************************************************
21 
22   =======================================================================
23 
24   Support for AES128 and AES256 CMAC in Nettle.
25 
26   */
27 
28 #include "config.h"
29 
30 #include "sysincl.h"
31 
32 #include <nettle/cmac.h>
33 
34 #include "cmac.h"
35 #include "memory.h"
36 
37 struct CMC_Instance_Record {
38   int key_length;
39   union {
40     struct cmac_aes128_ctx aes128;
41     struct cmac_aes256_ctx aes256;
42   } context;
43 };
44 
45 /* ================================================== */
46 
47 int
CMC_GetKeyLength(CMC_Algorithm algorithm)48 CMC_GetKeyLength(CMC_Algorithm algorithm)
49 {
50   if (algorithm == CMC_AES128)
51     return AES128_KEY_SIZE;
52   else if (algorithm == CMC_AES256)
53     return AES256_KEY_SIZE;
54   return 0;
55 }
56 
57 /* ================================================== */
58 
59 CMC_Instance
CMC_CreateInstance(CMC_Algorithm algorithm,const unsigned char * key,int length)60 CMC_CreateInstance(CMC_Algorithm algorithm, const unsigned char *key, int length)
61 {
62   CMC_Instance inst;
63 
64   if (length <= 0 || length != CMC_GetKeyLength(algorithm))
65     return NULL;
66 
67   inst = MallocNew(struct CMC_Instance_Record);
68   inst->key_length = length;
69 
70   switch (length) {
71     case AES128_KEY_SIZE:
72       cmac_aes128_set_key(&inst->context.aes128, key);
73       break;
74     case AES256_KEY_SIZE:
75       cmac_aes256_set_key(&inst->context.aes256, key);
76       break;
77     default:
78       assert(0);
79   }
80 
81   return inst;
82 }
83 
84 /* ================================================== */
85 
86 int
CMC_Hash(CMC_Instance inst,const void * in,int in_len,unsigned char * out,int out_len)87 CMC_Hash(CMC_Instance inst, const void *in, int in_len, unsigned char *out, int out_len)
88 {
89   if (in_len < 0 || out_len < 0)
90     return 0;
91 
92   if (out_len > CMAC128_DIGEST_SIZE)
93     out_len = CMAC128_DIGEST_SIZE;
94 
95   switch (inst->key_length) {
96     case AES128_KEY_SIZE:
97       cmac_aes128_update(&inst->context.aes128, in_len, in);
98       cmac_aes128_digest(&inst->context.aes128, out_len, out);
99       break;
100     case AES256_KEY_SIZE:
101       cmac_aes256_update(&inst->context.aes256, in_len, in);
102       cmac_aes256_digest(&inst->context.aes256, out_len, out);
103       break;
104     default:
105       assert(0);
106   }
107 
108   return out_len;
109 }
110 
111 /* ================================================== */
112 
113 void
CMC_DestroyInstance(CMC_Instance inst)114 CMC_DestroyInstance(CMC_Instance inst)
115 {
116   Free(inst);
117 }
118