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-2019 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 1.9.6
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 md2Oid[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02};
69 
70 //Common interface for hash algorithms
72 {
73  "MD2",
74  md2Oid,
75  sizeof(md2Oid),
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  //Allocate a memory buffer to hold the MD2 context
100  Md2Context *context = cryptoAllocMem(sizeof(Md2Context));
101  //Failed to allocate memory?
102  if(context == NULL)
103  return ERROR_OUT_OF_MEMORY;
104 
105  //Initialize the MD2 context
106  md2Init(context);
107  //Digest the message
108  md2Update(context, data, length);
109  //Finalize the MD2 message digest
110  md2Final(context, digest);
111 
112  //Free previously allocated memory
113  cryptoFreeMem(context);
114  //Successful processing
115  return NO_ERROR;
116 }
117 
118 
119 /**
120  * @brief Initialize MD2 message digest context
121  * @param[in] context Pointer to the MD2 context to initialize
122  **/
123 
124 void md2Init(Md2Context *context)
125 {
126  //Initialize the 48-byte buffer X
127  cryptoMemset(context->x, 0, 48);
128  //Clear checksum
129  cryptoMemset(context->c, 0, 16);
130  //Number of bytes in the buffer
131  context->size = 0;
132 }
133 
134 
135 /**
136  * @brief Update the MD2 context with a portion of the message being hashed
137  * @param[in] context Pointer to the MD2 context
138  * @param[in] data Pointer to the buffer being hashed
139  * @param[in] length Length of the buffer
140  **/
141 
142 void md2Update(Md2Context *context, const void *data, size_t length)
143 {
144  size_t n;
145 
146  //Process the incoming data
147  while(length > 0)
148  {
149  //The buffer can hold at most 16 bytes
150  n = MIN(length, 16 - context->size);
151 
152  //Copy the data to the buffer
153  cryptoMemcpy(context->m + context->size, data, n);
154 
155  //Update the MD2 context
156  context->size += n;
157  //Advance the data pointer
158  data = (uint8_t *) data + n;
159  //Remaining bytes to process
160  length -= n;
161 
162  //Process message in 16-word blocks
163  if(context->size == 16)
164  {
165  //Transform the 16-word block
166  md2ProcessBlock(context->m, context->x, context->c);
167  //Empty the buffer
168  context->size = 0;
169  }
170  }
171 }
172 
173 
174 /**
175  * @brief Finish the MD2 message digest
176  * @param[in] context Pointer to the MD2 context
177  * @param[out] digest Calculated digest (optional parameter)
178  **/
179 
180 void md2Final(Md2Context *context, uint8_t *digest)
181 {
182  uint_t n;
183 
184  //Pad the message so that its length is congruent to 0 modulo 16
185  n = 16 - context->size;
186 
187  //Append padding bytes
188  cryptoMemset(context->m + context->size, n, n);
189  //Transform the 16-word block
190  md2ProcessBlock(context->m, context->x, context->c);
191 
192  //Append the checksum
193  cryptoMemcpy(context->m, context->c, 16);
194  //Transform the 16-word block
195  md2ProcessBlock(context->m, context->x, context->c);
196 
197  //Copy the resulting digest
198  if(digest != NULL)
199  cryptoMemcpy(digest, context->digest, MD2_DIGEST_SIZE);
200 }
201 
202 
203 /**
204  * @brief Process message in 16-word blocks
205  * @param[in] m 16-byte data block to process
206  * @param[in,out] x 48-byte buffer
207  * @param[in,out] c 16-byte checksum
208  **/
209 
210 void md2ProcessBlock(const uint8_t *m, uint8_t *x, uint8_t *c)
211 {
212  uint_t j;
213  uint_t k;
214  uint8_t t;
215 
216  //Update checksum
217  for(t = c[15], j = 0; j < 16; j++)
218  {
219  c[j] ^= s[m[j] ^ t];
220  t = c[j];
221  }
222 
223  //Copy current block into X
224  for(j = 0; j < 16; j++)
225  {
226  x[16 + j] = m[j];
227  x[32 + j] = x[16 + j] ^ x[j];
228  }
229 
230  //Encrypt block (18 rounds)
231  for(t = 0, j = 0; j < 18; j++)
232  {
233  //Round j
234  for(k = 0; k < 48; k++)
235  {
236  x[k] ^= s[t];
237  t = x[k];
238  }
239 
240  //Set t to (t + j) modulo 256
241  t = (t + j) & 0xFF;
242  }
243 }
244 
245 #endif
uint8_t length
Definition: dtls_misc.h:149
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:142
#define MD2_BLOCK_SIZE
Definition: md2.h:38
void(* HashAlgoInit)(void *context)
Definition: crypto.h:1094
const uint8_t md2Oid[8]
Definition: md2.c:68
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
void md2Init(Md2Context *context)
Initialize MD2 message digest context.
Definition: md2.c:124
void(* HashAlgoUpdate)(void *context, const void *data, size_t length)
Definition: crypto.h:1095
uint8_t t
Definition: llmnr_common.h:81
uint8_t m[16]
Definition: md2.h:66
#define FALSE
Definition: os_port.h:46
error_t
Error codes.
Definition: error.h:42
uint8_t digest[16]
Definition: md2.h:64
size_t size
Definition: md2.h:68
uint8_t x[48]
Definition: md2.h:63
General definitions for cryptographic algorithms.
MD2 algorithm context.
Definition: md2.h:58
void md2Final(Md2Context *context, uint8_t *digest)
Finish the MD2 message digest.
Definition: md2.c:180
#define MIN(a, b)
Definition: os_port.h:62
void(* HashAlgoFinal)(void *context, uint8_t *digest)
Definition: crypto.h:1096
#define MD2_DIGEST_SIZE
Definition: md2.h:40
#define cryptoMemset(p, value, length)
Definition: crypto.h:636
uint8_t m
Definition: ndp.h:302
uint8_t n
uint8_t c[16]
Definition: md2.h:67
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:642
MD2 (Message-Digest Algorithm)
#define cryptoFreeMem(p)
Definition: crypto.h:630
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:625
#define MD2_MIN_PAD_SIZE
Definition: md2.h:42
Common interface for hash algorithms.
Definition: crypto.h:1128
unsigned int uint_t
Definition: compiler_port.h:45
uint8_t data[]
Definition: dtls_misc.h:176
error_t(* HashAlgoCompute)(const void *data, size_t length, uint8_t *digest)
Definition: crypto.h:1093
void md2ProcessBlock(const uint8_t *m, uint8_t *x, uint8_t *c)
Process message in 16-word blocks.
Definition: md2.c:210
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:513
const HashAlgo md2HashAlgo
Definition: md2.c:71