md2.c
Go to the documentation of this file.
1 /**
2  * @file md2.c
3  * @brief MD2 (Message-Digest Algorithm)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * The MD2 algorithm takes as input a message of arbitrary length and produces
30  * as output a 128-bit message digest of the input. Refer to RFC 1319
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 2.4.4
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
38 
39 //Dependencies
40 #include "core/crypto.h"
41 #include "hash/md2.h"
42 
43 //Check crypto library configuration
44 #if (MD2_SUPPORT == ENABLED)
45 
46 //MD2 constants
47 static const uint8_t s[256] =
48 {
49  0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
50  0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
51  0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
52  0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
53  0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
54  0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
55  0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
56  0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
57  0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
58  0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
59  0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
60  0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
61  0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
62  0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
63  0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
64  0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14,
65 };
66 
67 //MD2 object identifier (1.2.840.113549.2.2)
68 const uint8_t MD2_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02};
69 
70 //Common interface for hash algorithms
72 {
73  "MD2",
74  MD2_OID,
75  sizeof(MD2_OID),
76  sizeof(Md2Context),
80  FALSE,
85  NULL
86 };
87 
88 
89 /**
90  * @brief Digest a message using MD2
91  * @param[in] data Pointer to the message being hashed
92  * @param[in] length Length of the message
93  * @param[out] digest Pointer to the calculated digest
94  * @return Error code
95  **/
96 
97 error_t md2Compute(const void *data, size_t length, uint8_t *digest)
98 {
99 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
100  Md2Context *context;
101 #else
102  Md2Context context[1];
103 #endif
104 
105  //Check parameters
106  if(data == NULL && length != 0)
108 
109  if(digest == NULL)
111 
112 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
113  //Allocate a memory buffer to hold the MD2 context
114  context = cryptoAllocMem(sizeof(Md2Context));
115  //Failed to allocate memory?
116  if(context == NULL)
117  return ERROR_OUT_OF_MEMORY;
118 #endif
119 
120  //Initialize the MD2 context
121  md2Init(context);
122  //Digest the message
123  md2Update(context, data, length);
124  //Finalize the MD2 message digest
125  md2Final(context, digest);
126 
127 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
128  //Free previously allocated memory
129  cryptoFreeMem(context);
130 #endif
131 
132  //Successful operation
133  return NO_ERROR;
134 }
135 
136 
137 /**
138  * @brief Initialize MD2 message digest context
139  * @param[in] context Pointer to the MD2 context to initialize
140  **/
141 
142 void md2Init(Md2Context *context)
143 {
144  //Initialize the 48-byte buffer X
145  osMemset(context->x, 0, 48);
146  //Clear checksum
147  osMemset(context->c, 0, 16);
148  //Number of bytes in the buffer
149  context->size = 0;
150 }
151 
152 
153 /**
154  * @brief Update the MD2 context with a portion of the message being hashed
155  * @param[in] context Pointer to the MD2 context
156  * @param[in] data Pointer to the buffer being hashed
157  * @param[in] length Length of the buffer
158  **/
159 
160 void md2Update(Md2Context *context, const void *data, size_t length)
161 {
162  size_t n;
163 
164  //Process the incoming data
165  while(length > 0)
166  {
167  //The buffer can hold at most 16 bytes
168  n = MIN(length, 16 - context->size);
169 
170  //Copy the data to the buffer
171  osMemcpy(context->m + context->size, data, n);
172 
173  //Update the MD2 context
174  context->size += n;
175  //Advance the data pointer
176  data = (uint8_t *) data + n;
177  //Remaining bytes to process
178  length -= n;
179 
180  //Process message in 16-word blocks
181  if(context->size == 16)
182  {
183  //Transform the 16-word block
184  md2ProcessBlock(context->m, context->x, context->c);
185  //Empty the buffer
186  context->size = 0;
187  }
188  }
189 }
190 
191 
192 /**
193  * @brief Finish the MD2 message digest
194  * @param[in] context Pointer to the MD2 context
195  * @param[out] digest Calculated digest (optional parameter)
196  **/
197 
198 void md2Final(Md2Context *context, uint8_t *digest)
199 {
200  uint_t n;
201 
202  //Pad the message so that its length is congruent to 0 modulo 16
203  n = 16 - context->size;
204 
205  //Append padding bytes
206  osMemset(context->m + context->size, n, n);
207  //Transform the 16-word block
208  md2ProcessBlock(context->m, context->x, context->c);
209 
210  //Append the checksum
211  osMemcpy(context->m, context->c, 16);
212  //Transform the 16-word block
213  md2ProcessBlock(context->m, context->x, context->c);
214 
215  //Copy the resulting digest
216  if(digest != NULL)
217  {
218  osMemcpy(digest, context->digest, MD2_DIGEST_SIZE);
219  }
220 }
221 
222 
223 /**
224  * @brief Process message in 16-word blocks
225  * @param[in] m 16-byte data block to process
226  * @param[in,out] x 48-byte buffer
227  * @param[in,out] c 16-byte checksum
228  **/
229 
230 void md2ProcessBlock(const uint8_t *m, uint8_t *x, uint8_t *c)
231 {
232  uint_t j;
233  uint_t k;
234  uint8_t t;
235 
236  //Update checksum
237  for(t = c[15], j = 0; j < 16; j++)
238  {
239  c[j] ^= s[m[j] ^ t];
240  t = c[j];
241  }
242 
243  //Copy current block into X
244  for(j = 0; j < 16; j++)
245  {
246  x[16 + j] = m[j];
247  x[32 + j] = x[16 + j] ^ x[j];
248  }
249 
250  //Encrypt block (18 rounds)
251  for(t = 0, j = 0; j < 18; j++)
252  {
253  //Round j
254  for(k = 0; k < 48; k++)
255  {
256  x[k] ^= s[t];
257  t = x[k];
258  }
259 
260  //Set t to (t + j) modulo 256
261  t = (t + j) & 0xFF;
262  }
263 }
264 
265 #endif
void md2Update(Md2Context *context, const void *data, size_t length)
Update the MD2 context with a portion of the message being hashed.
Definition: md2.c:160
#define MD2_BLOCK_SIZE
Definition: md2.h:38
void(* HashAlgoInit)(void *context)
Definition: crypto.h:991
uint8_t x
Definition: lldp_ext_med.h:211
uint8_t t
Definition: lldp_ext_med.h:212
uint8_t data[]
Definition: ethernet.h:222
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
void md2Init(Md2Context *context)
Initialize MD2 message digest context.
Definition: md2.c:142
void(* HashAlgoUpdate)(void *context, const void *data, size_t length)
Definition: crypto.h:993
uint8_t m[16]
Definition: md2.h:64
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
uint8_t digest[16]
Definition: md2.h:62
size_t size
Definition: md2.h:66
uint8_t x[48]
Definition: md2.h:61
General definitions for cryptographic algorithms.
MD2 algorithm context.
Definition: md2.h:57
void md2Final(Md2Context *context, uint8_t *digest)
Finish the MD2 message digest.
Definition: md2.c:198
uint8_t length
Definition: tcp.h:368
#define MIN(a, b)
Definition: os_port.h:63
void(* HashAlgoFinal)(void *context, uint8_t *digest)
Definition: crypto.h:995
#define MD2_DIGEST_SIZE
Definition: md2.h:40
const uint8_t MD2_OID[8]
Definition: md2.c:68
uint8_t m
Definition: ndp.h:304
uint8_t n
uint8_t c[16]
Definition: md2.h:65
MD2 (Message-Digest Algorithm)
#define cryptoFreeMem(p)
Definition: crypto.h:791
error_t md2Compute(const void *data, size_t length, uint8_t *digest)
Digest a message using MD2.
Definition: md2.c:97
#define cryptoAllocMem(size)
Definition: crypto.h:786
#define MD2_MIN_PAD_SIZE
Definition: md2.h:42
uint8_t s
Definition: igmp_common.h:234
Common interface for hash algorithms.
Definition: crypto.h:1046
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:135
error_t(* HashAlgoCompute)(const void *data, size_t length, uint8_t *digest)
Definition: crypto.h:988
void md2ProcessBlock(const uint8_t *m, uint8_t *x, uint8_t *c)
Process message in 16-word blocks.
Definition: md2.c:230
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
const HashAlgo md2HashAlgo
Definition: md2.c:71