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