Skip to content

Commit 41068fe

Browse files
committed
Add OpenSSL demo used to prove corecode/dma#126
1 parent 06155b1 commit 41068fe

File tree

5 files changed

+245
-0
lines changed

5 files changed

+245
-0
lines changed

demos/openssl/hmac-md5/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
hmac-md5-test1
2+
hmac-md5-test3

demos/openssl/hmac-md5/Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
LDADD+= -lcrypto
2+
3+
PROGS= hmac-md5-test1 hmac-md5-test3
4+
5+
all: .PHONY ${PROGS}
6+
7+
check: .PHONY
8+
.for prog in ${PROGS} hmac-md5-test.py
9+
./${prog} --short
10+
./${prog} --long
11+
.endfor
12+
13+
hmac-md5-test1: hmac-md5-test.c
14+
${CC} -o ${.TARGET} ${LDADD} ${.ALLSRC}
15+
16+
hmac-md5-test3: hmac-md5-test.c
17+
${CC} -o ${.TARGET} ${LDADD} ${.ALLSRC}

demos/openssl/hmac-md5/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Code in the hmac-md5-test.c demo program comes from https://github.com/corecode/dma .
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*
2+
* Copyright (c) 2008 The DragonFly Project. All rights reserved.
3+
*
4+
* This code is derived from software contributed to The DragonFly Project
5+
* by Matthias Schmidt <matthias@dragonflybsd.org>, University of Marburg,
6+
* Germany.
7+
*
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions
10+
* are met:
11+
*
12+
* 1. Redistributions of source code must retain the above copyright
13+
* notice, this list of conditions and the following disclaimer.
14+
* 2. Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in
16+
* the documentation and/or other materials provided with the
17+
* distribution.
18+
* 3. Neither the name of The DragonFly Project nor the names of its
19+
* contributors may be used to endorse or promote products derived
20+
* from this software without specific, prior written permission.
21+
*
22+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23+
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26+
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27+
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32+
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33+
* SUCH DAMAGE.
34+
*/
35+
36+
#include <openssl/opensslv.h>
37+
#if (OPENSSL_VERSION_NUMBER >= 0x300000L)
38+
#define IS_OPENSSL3 1
39+
#endif
40+
41+
#include <openssl/x509.h>
42+
#include <openssl/md5.h>
43+
#include <openssl/ssl.h>
44+
#include <openssl/err.h>
45+
#include <openssl/pem.h>
46+
#include <openssl/rand.h>
47+
48+
#include <assert.h>
49+
#include <stdio.h>
50+
#include <string.h>
51+
52+
/*
53+
* hmac_md5() taken out of RFC 2104. This RFC was written by H. Krawczyk,
54+
* M. Bellare and R. Canetti.
55+
*
56+
* text pointer to data stream
57+
* text_len length of data stream
58+
* key pointer to authentication key
59+
* key_len length of authentication key
60+
* digest caller digest to be filled int
61+
*/
62+
void
63+
hmac_md5(unsigned char *text, int text_len, unsigned char *key, int key_len,
64+
unsigned char* digest)
65+
{
66+
#ifdef IS_OPENSSL3
67+
const EVP_MD *md;
68+
EVP_MD_CTX *context;
69+
#else
70+
MD5_CTX context;
71+
#endif
72+
unsigned char k_ipad[65]; /* inner padding -
73+
* key XORd with ipad
74+
*/
75+
unsigned char k_opad[65]; /* outer padding -
76+
* key XORd with opad
77+
*/
78+
unsigned char tk[16];
79+
int i;
80+
81+
#ifdef IS_OPENSSL3
82+
context = EVP_MD_CTX_new();
83+
assert(context != NULL);
84+
85+
md = EVP_md5();
86+
assert(md != NULL);
87+
#endif
88+
89+
/* if key is longer than 64 bytes reset it to key=MD5(key) */
90+
if (key_len > 64) {
91+
#ifdef IS_OPENSSL3
92+
EVP_DigestInit_ex(context, md, NULL);
93+
EVP_DigestUpdate(context, key, key_len);
94+
EVP_DigestFinal_ex(context, tk, NULL);
95+
#else
96+
MD5_Init(&context);
97+
MD5_Update(&context, key, key_len);
98+
MD5_Final(tk, &context);
99+
#endif
100+
key = tk;
101+
key_len = 16;
102+
}
103+
104+
/*
105+
* the HMAC_MD5 transform looks like:
106+
*
107+
* MD5(K XOR opad, MD5(K XOR ipad, text))
108+
*
109+
* where K is an n byte key
110+
* ipad is the byte 0x36 repeated 64 times
111+
*
112+
* opad is the byte 0x5c repeated 64 times
113+
* and text is the data being protected
114+
*/
115+
116+
/* start out by storing key in pads */
117+
bzero( k_ipad, sizeof k_ipad);
118+
bzero( k_opad, sizeof k_opad);
119+
bcopy( key, k_ipad, key_len);
120+
bcopy( key, k_opad, key_len);
121+
122+
/* XOR key with ipad and opad values */
123+
for (i=0; i<64; i++) {
124+
k_ipad[i] ^= 0x36;
125+
k_opad[i] ^= 0x5c;
126+
}
127+
128+
#ifdef IS_OPENSSL3
129+
/**
130+
* Perform inner MD5.
131+
*/
132+
133+
/* Init context for first pass. */
134+
EVP_DigestInit_ex(context, md, NULL);
135+
/* Start with inner pad. */
136+
EVP_DigestUpdate(context, k_ipad, 64);
137+
/* Update with text of datagram. */
138+
EVP_DigestUpdate(context, text, text_len);
139+
/* Finish up first pass. */
140+
EVP_DigestFinal_ex(context, digest, NULL);
141+
142+
/**
143+
* Perform outer MD5.
144+
*/
145+
146+
/* Re-init context for second pass. */
147+
EVP_DigestInit_ex(context, md, NULL);
148+
/* Start with outer pad. */
149+
EVP_DigestUpdate(context, k_opad, 64);
150+
/* Update with results of first hash. */
151+
EVP_DigestUpdate(context, digest, 16);
152+
/* Finish up second pass. */
153+
EVP_DigestFinal_ex(context, digest, NULL);
154+
155+
EVP_MD_CTX_free(context);
156+
#else
157+
/*
158+
* perform inner MD5
159+
*/
160+
MD5_Init(&context); /* init context for 1st
161+
* pass */
162+
MD5_Update(&context, k_ipad, 64); /* start with inner pad */
163+
MD5_Update(&context, text, text_len); /* then text of datagram */
164+
165+
MD5_Final(digest, &context); /* finish up 1st pass */
166+
/*
167+
* perform outer MD5
168+
*/
169+
MD5_Init(&context); /* init context for 2nd
170+
* pass */
171+
MD5_Update(&context, k_opad, 64); /* start with outer pad */
172+
MD5_Update(&context, digest, 16); /* then results of 1st
173+
* hash */
174+
MD5_Final(digest, &context); /* finish up 2nd pass */
175+
#endif
176+
}
177+
178+
const char *SHORT_AUTH_KEY = "this is a passcode";
179+
const char *LONG_AUTH_KEY = "this is a SUPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPER LONG passcode";
180+
181+
int
182+
main(int argc, const char *argv[])
183+
{
184+
const char *auth_key = (argc == 0 || strcmp(argv[1], "--short") == 0) ?
185+
SHORT_AUTH_KEY : LONG_AUTH_KEY;
186+
187+
char *text = "abcdefghijklmnop";
188+
unsigned char digest[8192] = {0};
189+
190+
hmac_md5(
191+
(unsigned char*)text, strlen(text),
192+
(unsigned char*)auth_key, strlen(auth_key),
193+
digest);
194+
195+
printf("key: %s\n", auth_key);
196+
printf("text: %s\n", text);
197+
printf("digest: ");
198+
199+
for (int i = 0; digest[i] != '\0'; i++)
200+
printf("%02x", digest[i]);
201+
printf("\n");
202+
203+
return 0;
204+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env python3
2+
import argparse
3+
import hmac
4+
import sys
5+
6+
SHORT_KEY = b"this is a passcode"
7+
LONG_KEY = b"this is a SUPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPER LONG passcode"
8+
9+
parser = argparse.ArgumentParser()
10+
parser.add_argument("--short", action="store_true", dest="want_short_key")
11+
parser.add_argument("--long", action="store_false", dest="want_short_key")
12+
args = parser.parse_args()
13+
14+
key = SHORT_KEY if args.want_short_key else LONG_KEY
15+
16+
text = b"abcdefghijklmnop"
17+
hexdigest_len = 12
18+
19+
print("key:", key.decode())
20+
print("text:", text.decode())
21+
print("digest:", hmac.new(key, text, "MD5").hexdigest()[:hexdigest_len])

0 commit comments

Comments
 (0)