libtests/md501: Use test cases of RFC 2202

This commit is contained in:
Sebastian Huber
2012-12-16 21:34:13 +01:00
parent f95d74a4ad
commit c40f36b08b
2 changed files with 202 additions and 162 deletions

View File

@@ -20,174 +20,213 @@
#include <md5.h> #include <md5.h>
static const uint32_t sample_data[] = { #ifndef MD5_BLOCK_SIZE
0U, #define MD5_BLOCK_SIZE 64
1U, #endif
1U,
2U, #ifndef MD5_DIGEST_LENGTH
3U, #define MD5_DIGEST_LENGTH 16
5U, #endif
8U,
13U, /* Test cases according to RFC 2202 */
21U,
34U, static const uint8_t key_1[] = {
55U, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
89U, 0x0b, 0x0b, 0x0b
144U,
233U,
377U,
610U,
987U,
1597U,
2584U,
4181U,
6765U,
10946U,
17711U,
28657U,
46368U,
75025U,
121393U,
196418U,
317811U,
514229U,
832040U,
1346269U,
2178309U,
3524578U,
5702887U,
9227465U,
14930352U,
24157817U,
39088169U,
63245986U,
102334155U,
165580141U,
267914296U,
433494437U,
701408733U,
1134903170U,
1836311903U,
2971215073U
}; };
static const uint8_t static const uint8_t data_1[] = {
expected_digests[RTEMS_ARRAY_SIZE(sample_data)][16] = { 'H', 'i', ' ', 'T', 'h', 'e', 'r', 'e'
{ 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e },
{ 0x93, 0xb8, 0x85, 0xad, 0xfe, 0x0d, 0xa0, 0x89,
0xcd, 0xf6, 0x34, 0x90, 0x4f, 0xd5, 0x9f, 0x71 },
{ 0xc4, 0x10, 0x3f, 0x12, 0x2d, 0x27, 0x67, 0x7c,
0x9d, 0xb1, 0x44, 0xca, 0xe1, 0x39, 0x4a, 0x66 },
{ 0x69, 0x3e, 0x9a, 0xf8, 0x4d, 0x3d, 0xfc, 0xc7,
0x1e, 0x64, 0x0e, 0x00, 0x5b, 0xdc, 0x5e, 0x2e },
{ 0xf1, 0xd3, 0xff, 0x84, 0x43, 0x29, 0x77, 0x32,
0x86, 0x2d, 0xf2, 0x1d, 0xc4, 0xe5, 0x72, 0x62 },
{ 0xca, 0x9c, 0x49, 0x1a, 0xc6, 0x6b, 0x2c, 0x62,
0x50, 0x08, 0x82, 0xe9, 0x3f, 0x37, 0x19, 0xa8 },
{ 0x73, 0x19, 0x46, 0x88, 0x47, 0xd7, 0xb1, 0xae,
0xe4, 0x0d, 0xbf, 0x5d, 0xd9, 0x63, 0xc9, 0x99 },
{ 0xd3, 0x10, 0xa4, 0x04, 0x83, 0xf9, 0x39, 0x9d,
0xd7, 0xed, 0x17, 0x12, 0xe0, 0xfd, 0xd7, 0x02 },
{ 0xfa, 0x5a, 0xd9, 0xa8, 0x55, 0x7e, 0x5a, 0x84,
0xcf, 0x23, 0xe5, 0x2d, 0x3d, 0x3a, 0xdf, 0x77 },
{ 0x7d, 0x54, 0x9f, 0x72, 0x14, 0x2d, 0xc6, 0xd3,
0x55, 0xff, 0x74, 0x2e, 0xdf, 0xe0, 0xd2, 0x4c },
{ 0xdc, 0x3e, 0xd0, 0xe0, 0x41, 0x89, 0x4e, 0x29,
0xac, 0xfd, 0xb8, 0xf6, 0xf0, 0xd7, 0xcb, 0x06 },
{ 0x32, 0xe0, 0x77, 0xfa, 0xba, 0x23, 0x2f, 0x08,
0xb1, 0x6a, 0xe0, 0x82, 0xaf, 0xd1, 0x66, 0x25 },
{ 0x9e, 0x7f, 0x6f, 0xa5, 0xa4, 0x5d, 0xad, 0x95,
0xf3, 0xa7, 0x2e, 0x1c, 0x5a, 0xec, 0x89, 0x36 },
{ 0xcb, 0x7d, 0xab, 0x55, 0xe7, 0x17, 0x7d, 0xf2,
0xc7, 0x28, 0xa1, 0x7b, 0xef, 0xe9, 0x04, 0xe9 },
{ 0x5c, 0x90, 0x2d, 0x82, 0x30, 0x42, 0x74, 0xc5,
0x71, 0x21, 0xfb, 0x7b, 0x3e, 0x0e, 0x02, 0x5f },
{ 0x5c, 0x49, 0xa3, 0xd4, 0xa3, 0x19, 0xc5, 0x61,
0x3f, 0x1a, 0x00, 0x1b, 0x50, 0xc5, 0xff, 0x69 },
{ 0xc9, 0xf9, 0xc8, 0xba, 0x6f, 0x99, 0x68, 0x56,
0x25, 0x84, 0x3b, 0xdc, 0x10, 0x3c, 0xef, 0x5d },
{ 0x1f, 0xfa, 0x2f, 0x79, 0xbc, 0x11, 0xbb, 0x25,
0xed, 0x71, 0x24, 0x4b, 0xb6, 0x98, 0x43, 0x4d },
{ 0xe3, 0x7d, 0xca, 0x05, 0x2c, 0x66, 0xb6, 0x94,
0xb6, 0x1d, 0x4e, 0xb8, 0xcf, 0x96, 0x4f, 0x92 },
{ 0xe1, 0x87, 0xd2, 0xe8, 0x01, 0xf1, 0xa8, 0x8a,
0x85, 0x75, 0x88, 0x53, 0x1e, 0x89, 0xba, 0x5b },
{ 0x9f, 0xe1, 0x02, 0x79, 0x78, 0x66, 0xde, 0xc1,
0xa8, 0x19, 0x43, 0xbb, 0x12, 0xa6, 0x83, 0x25 },
{ 0xd2, 0xc9, 0xb2, 0xc2, 0x33, 0x6b, 0xe6, 0x00,
0x54, 0xd9, 0xee, 0xdc, 0x73, 0x56, 0x63, 0x5a },
{ 0x8d, 0x22, 0x28, 0x5d, 0x43, 0x7e, 0x5e, 0x7c,
0xc7, 0x95, 0x99, 0x14, 0x6e, 0xdb, 0x0b, 0x8e },
{ 0xb0, 0x94, 0x12, 0xcf, 0xac, 0xb8, 0x62, 0x66,
0x82, 0x42, 0xda, 0x19, 0x2d, 0xf4, 0x9c, 0xfc },
{ 0x6d, 0xe2, 0xdb, 0x98, 0x90, 0x1c, 0xd1, 0xa0,
0x33, 0x5b, 0xe8, 0x41, 0x85, 0xf6, 0xb0, 0xa9 },
{ 0xdd, 0x5a, 0x0e, 0x73, 0x04, 0x50, 0x0c, 0x82,
0x1c, 0xac, 0x16, 0x7a, 0xfc, 0x2c, 0x49, 0x9b },
{ 0x50, 0xb1, 0x37, 0xe3, 0x2b, 0x8d, 0x73, 0x0e,
0x71, 0xef, 0x80, 0x04, 0x77, 0xe3, 0x33, 0x88 },
{ 0x34, 0xb4, 0x5c, 0xc2, 0xc5, 0x9f, 0xa1, 0x38,
0x7a, 0x63, 0x72, 0x2d, 0x27, 0x9d, 0x7e, 0xe2 },
{ 0x1d, 0x80, 0x21, 0xb2, 0x30, 0x62, 0x00, 0xd0,
0x7f, 0x44, 0x7b, 0x02, 0x13, 0x84, 0x46, 0x06 },
{ 0xa9, 0x26, 0xa4, 0x59, 0x8f, 0xe3, 0x72, 0x63,
0xa9, 0xf3, 0xd9, 0xe1, 0x71, 0x8d, 0x53, 0x04 },
{ 0xbb, 0xcf, 0xc7, 0xe1, 0xb1, 0x05, 0x83, 0x36,
0x06, 0xd4, 0xc1, 0x7b, 0x59, 0x9b, 0x38, 0xd3 },
{ 0xe1, 0xb8, 0xab, 0x14, 0x9f, 0x77, 0x78, 0x48,
0x52, 0x46, 0xad, 0x11, 0x0d, 0x14, 0x1e, 0x5f },
{ 0x8e, 0xeb, 0x2d, 0xe2, 0x6d, 0xf3, 0xe0, 0xff,
0x77, 0x35, 0x46, 0x58, 0xb5, 0xa7, 0xa9, 0x81 },
{ 0xe6, 0x5a, 0xd2, 0x29, 0x38, 0x38, 0xc4, 0x49,
0x34, 0xad, 0x74, 0x93, 0x1b, 0x22, 0x4e, 0xd2 },
{ 0x72, 0xb3, 0x93, 0xea, 0xfb, 0xcd, 0xa3, 0xb6,
0x42, 0xd9, 0xd4, 0x32, 0xcf, 0x14, 0x0d, 0x99 },
{ 0xd6, 0xc2, 0x60, 0x2f, 0x28, 0xc2, 0xc8, 0x79,
0x3b, 0x98, 0x8b, 0x33, 0x5f, 0x55, 0xe5, 0xc6 },
{ 0x48, 0xa4, 0x0f, 0xc1, 0x6e, 0xe1, 0x9b, 0xbd,
0x5f, 0x55, 0x2f, 0x1d, 0x66, 0x0d, 0x6f, 0x2e },
{ 0x65, 0x85, 0x50, 0x04, 0xb5, 0xa6, 0x14, 0x93,
0xb4, 0xe3, 0x32, 0x49, 0x08, 0x27, 0x1a, 0xd4 },
{ 0xd1, 0xb2, 0xe5, 0xcd, 0x38, 0x11, 0xec, 0x0f,
0xe4, 0x84, 0x11, 0x46, 0x6c, 0x2e, 0x8d, 0x13 },
{ 0x59, 0x3d, 0x1e, 0x9c, 0x81, 0x51, 0x1d, 0x30,
0x93, 0x57, 0xaf, 0xde, 0x1f, 0x91, 0x15, 0x11 },
{ 0x57, 0x9d, 0x78, 0xd1, 0xf3, 0xc9, 0xa1, 0xdf,
0x0c, 0x68, 0x70, 0x60, 0x4b, 0xab, 0xa4, 0xb4 },
{ 0xba, 0x86, 0x0d, 0xd4, 0xda, 0xc8, 0x3e, 0x7a,
0x5c, 0xa5, 0xda, 0x2b, 0x51, 0x12, 0xca, 0xfb },
{ 0xda, 0x10, 0xff, 0x74, 0x10, 0xfe, 0x79, 0xa3,
0x33, 0x68, 0xac, 0x10, 0x99, 0x13, 0xc8, 0x2a },
{ 0xc5, 0x47, 0xa0, 0xd7, 0x8b, 0xcd, 0xc4, 0xc5,
0xdb, 0x0d, 0x5c, 0xba, 0x21, 0xba, 0xa9, 0x68 },
{ 0x8f, 0xa8, 0x7b, 0x3d, 0xfd, 0xd3, 0x41, 0x6b,
0xa7, 0x3f, 0xb0, 0x25, 0x7d, 0xe4, 0xa7, 0x48 },
{ 0xc9, 0x64, 0x99, 0x9c, 0xaa, 0x54, 0x7c, 0x95,
0xd0, 0x78, 0x97, 0x16, 0xfe, 0x55, 0xf7, 0x99 },
{ 0xa4, 0xea, 0xa3, 0x20, 0xb7, 0xa2, 0x71, 0xb7,
0xdd, 0x59, 0xca, 0x81, 0xe8, 0x19, 0x04, 0xb3 },
{ 0x11, 0x99, 0x0a, 0xab, 0x09, 0xa0, 0x7d, 0x96,
0x9e, 0x0a, 0xe6, 0x07, 0xe5, 0x6b, 0xfb, 0x7c }
}; };
static const uint8_t digest_1[MD5_DIGEST_LENGTH] = {
0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 0x13, 0xf4, 0x8e, 0xf8, 0x15,
0x8b, 0xfc, 0x9d
};
static const uint8_t key_2[] = {
'J', 'e', 'f', 'e'
};
static const uint8_t data_2[] = {
'w', 'h', 'a', 't', ' ', 'd', 'o', ' ', 'y', 'a', ' ', 'w', 'a', 'n', 't',
' ', 'f', 'o', 'r', ' ', 'n', 'o', 't', 'h', 'i', 'n', 'g', '?'
};
static const uint8_t digest_2[MD5_DIGEST_LENGTH] = {
0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, 0xea, 0xa8, 0x6e, 0x31, 0x0a,
0x5d, 0xb7, 0x38
};
static const uint8_t key_3[] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa
};
static const uint8_t data_3[] = {
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd
};
static const uint8_t digest_3[MD5_DIGEST_LENGTH] = {
0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, 0xdb, 0xb8, 0xc7, 0x33, 0xf0,
0xe8, 0xb3, 0xf6
};
static const uint8_t key_4[] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19
};
static const uint8_t data_4[] = {
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd
};
static const uint8_t digest_4[MD5_DIGEST_LENGTH] = {
0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, 0x3a, 0x75, 0x16, 0x47, 0x46,
0xff, 0xaa, 0x79
};
static const uint8_t key_5[] = {
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c
};
static const uint8_t data_5[] = {
'T', 'e', 's', 't', ' ', 'W', 'i', 't', 'h', ' ', 'T', 'r', 'u', 'n', 'c',
'a', 't', 'i', 'o', 'n'
};
static const uint8_t digest_5[MD5_DIGEST_LENGTH] = {
0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, 0xf9, 0xba, 0xb9, 0x95, 0x69,
0x0e, 0xfd, 0x4c
};
static const uint8_t key_6[] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa
};
static const uint8_t data_6[] = {
'T', 'e', 's', 't', ' ', 'U', 's', 'i', 'n', 'g', ' ', 'L', 'a', 'r', 'g',
'e', 'r', ' ', 'T', 'h', 'a', 'n', ' ', 'B', 'l', 'o', 'c', 'k', '-', 'S',
'i', 'z', 'e', ' ', 'K', 'e', 'y', ' ', '-', ' ', 'H', 'a', 's', 'h', ' ',
'K', 'e', 'y', ' ', 'F', 'i', 'r', 's', 't'
};
static const uint8_t digest_6[MD5_DIGEST_LENGTH] = {
0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, 0x0b, 0x62, 0xe6, 0xce, 0x61,
0xb9, 0xd0, 0xcd
};
static const uint8_t key_7[] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa
};
static const uint8_t data_7[] = {
'T', 'e', 's', 't', ' ', 'U', 's', 'i', 'n', 'g', ' ', 'L', 'a', 'r', 'g',
'e', 'r', ' ', 'T', 'h', 'a', 'n', ' ', 'B', 'l', 'o', 'c', 'k', '-', 'S',
'i', 'z', 'e', ' ', 'K', 'e', 'y', ' ', 'a', 'n', 'd', ' ', 'L', 'a', 'r',
'g', 'e', 'r', ' ', 'T', 'h', 'a', 'n', ' ', 'O', 'n', 'e', ' ', 'B', 'l',
'o', 'c', 'k', '-', 'S', 'i', 'z', 'e', ' ', 'D', 'a', 't', 'a'
};
static const uint8_t digest_7[MD5_DIGEST_LENGTH] = {
0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, 0x1f, 0xb1, 0xf5, 0x62, 0xdb,
0x3a, 0xa5, 0x3e
};
static void test_md5(
const uint8_t *key,
size_t key_size,
const uint8_t *data,
size_t data_size,
const uint8_t expected_digest[MD5_DIGEST_LENGTH]
)
{
MD5_CTX inner_ctx;
MD5_CTX outer_ctx;
uint8_t inner_digest[MD5_DIGEST_LENGTH];
uint8_t outer_digest[MD5_DIGEST_LENGTH];
uint8_t key_buf[MD5_DIGEST_LENGTH];
uint8_t buf[MD5_BLOCK_SIZE];
size_t i;
if (key_size > MD5_BLOCK_SIZE) {
MD5_CTX tmp_ctx;
MD5Init(&tmp_ctx);
MD5Update(&tmp_ctx, key, key_size);
MD5Final(&key_buf[0], &tmp_ctx);
key = &key_buf[0];
key_size = MD5_DIGEST_LENGTH;
}
/* Inner digest */
MD5Init(&inner_ctx);
/* Pad the key for the inner digest */
for (i = 0; i < key_size; ++i) {
buf[i] = key[i] ^ 0x36;
}
for (i = key_size; i < MD5_BLOCK_SIZE; ++i) {
buf[i] = 0x36;
}
MD5Update(&inner_ctx, &buf[0], MD5_BLOCK_SIZE);
MD5Update(&inner_ctx, data, data_size);
MD5Final(&inner_digest[0], &inner_ctx);
/* Outer digest */
MD5Init(&outer_ctx);
/* Pad the key for outer digest */
for (i = 0; i < key_size; ++i) {
buf[i] = key[i] ^ 0x5c;
}
for (i = key_size; i < MD5_BLOCK_SIZE; ++i) {
buf[i] = 0x5c;
}
MD5Update(&outer_ctx, &buf[0], MD5_BLOCK_SIZE);
MD5Update(&outer_ctx, &inner_digest[0], MD5_DIGEST_LENGTH);
MD5Final(&outer_digest[0], &outer_ctx);
rtems_test_assert(
memcmp(&outer_digest[0], expected_digest, sizeof(outer_digest)) == 0
);
}
static void test(void) static void test(void)
{ {
size_t n = RTEMS_ARRAY_SIZE(sample_data); test_md5(&key_1[0], sizeof(key_1), &data_1[0], sizeof(data_1), &digest_1[0]);
size_t i; test_md5(&key_2[0], sizeof(key_2), &data_2[0], sizeof(data_2), &digest_2[0]);
test_md5(&key_3[0], sizeof(key_3), &data_3[0], sizeof(data_3), &digest_3[0]);
for (i = 0; i < n; ++i) { test_md5(&key_4[0], sizeof(key_4), &data_4[0], sizeof(data_4), &digest_4[0]);
uint8_t digest[16]; test_md5(&key_5[0], sizeof(key_5), &data_5[0], sizeof(data_5), &digest_5[0]);
MD5_CTX ctx; test_md5(&key_6[0], sizeof(key_6), &data_6[0], sizeof(data_6), &digest_6[0]);
test_md5(&key_7[0], sizeof(key_7), &data_7[0], sizeof(data_7), &digest_7[0]);
MD5Init(&ctx);
MD5Update(&ctx, &sample_data [0], i);
MD5Final(&digest [0], &ctx);
rtems_test_assert(
memcmp(&digest[0], &expected_digests[i][0], sizeof(digest)) == 0
);
}
} }
static void Init(rtems_task_argument arg) static void Init(rtems_task_argument arg)

View File

@@ -11,3 +11,4 @@ directives:
concepts: concepts:
- Ensures that the MD5 digest is calucated correctly for a sample data set. - Ensures that the MD5 digest is calucated correctly for a sample data set.
- Test cases are from RFC 2202.