1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant / wrapper functions for libcrypto
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <openssl/opensslv.h>
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <openssl/md4.h>
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <openssl/md5.h>
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <openssl/sha.h>
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <openssl/des.h>
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <openssl/aes.h>
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <openssl/bn.h>
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <openssl/evp.h>
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "crypto.h"
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#if OPENSSL_VERSION_NUMBER < 0x00907000
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define DES_key_schedule des_key_schedule
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define DES_cblock des_cblock
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define DES_set_key(key, schedule) des_set_key((key), *(schedule))
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define DES_ecb_encrypt(input, output, ks, enc) \
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	des_ecb_encrypt((input), (output), *(ks), (enc))
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* openssl < 0.9.7 */
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	MD4_CTX ctx;
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t i;
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	MD4_Init(&ctx);
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < num_elem; i++)
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD4_Update(&ctx, addr[i], len[i]);
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	MD4_Final(mac, &ctx);
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 pkey[8], next, tmp;
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int i;
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DES_key_schedule ks;
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Add parity bits to the key */
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	next = 0;
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < 7; i++) {
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		tmp = key[i];
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pkey[i] = (tmp >> i) | next | 1;
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		next = tmp << (7 - i);
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pkey[i] = next | 1;
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DES_set_key(&pkey, &ks);
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			DES_ENCRYPT);
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	MD5_CTX ctx;
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t i;
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	MD5_Init(&ctx);
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < num_elem; i++)
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5_Update(&ctx, addr[i], len[i]);
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	MD5_Final(mac, &ctx);
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SHA_CTX ctx;
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t i;
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SHA1_Init(&ctx);
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < num_elem; i++)
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1_Update(&ctx, addr[i], len[i]);
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SHA1_Final(mac, &ctx);
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef CONFIG_NO_FIPS186_2_PRF
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void sha1_transform(u8 *state, const u8 data[64])
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SHA_CTX context;
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(&context, 0, sizeof(context));
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(&context.h0, state, 5 * 4);
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SHA1_Transform(&context, data);
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(state, &context.h0, 5 * 4);
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 xkey[64];
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u32 t[5], _t[5];
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int i, j, m, k;
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 *xpos = x;
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u32 carry;
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (seed_len > sizeof(xkey))
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		seed_len = sizeof(xkey);
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* FIPS 186-2 + change notice 1 */
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(xkey, seed, seed_len);
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memset(xkey + seed_len, 0, 64 - seed_len);
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	t[0] = 0x67452301;
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	t[1] = 0xEFCDAB89;
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	t[2] = 0x98BADCFE;
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	t[3] = 0x10325476;
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	t[4] = 0xC3D2E1F0;
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	m = xlen / 40;
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (j = 0; j < m; j++) {
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* XSEED_j = 0 */
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (i = 0; i < 2; i++) {
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			/* XVAL = (XKEY + XSEED_j) mod 2^b */
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			/* w_i = G(t, XVAL) */
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(_t, t, 20);
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			sha1_transform((u8 *) _t, xkey);
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			_t[0] = host_to_be32(_t[0]);
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			_t[1] = host_to_be32(_t[1]);
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			_t[2] = host_to_be32(_t[2]);
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			_t[3] = host_to_be32(_t[3]);
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			_t[4] = host_to_be32(_t[4]);
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(xpos, _t, 20);
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			/* XKEY = (1 + XKEY + w_i) mod 2^b */
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			carry = 1;
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			for (k = 19; k >= 0; k--) {
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				carry += xkey[k] + xpos[k];
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				xkey[k] = carry & 0xff;
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				carry >>= 8;
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			}
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			xpos += 20;
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* x_j = w_0|w_1 */
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_NO_FIPS186_2_PRF */
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid * aes_encrypt_init(const u8 *key, size_t len)
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	AES_KEY *ak;
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ak = os_malloc(sizeof(*ak));
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ak == NULL)
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (AES_set_encrypt_key(key, 8 * len, ak) < 0) {
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(ak);
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ak;
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	AES_encrypt(plain, crypt, ctx);
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid aes_encrypt_deinit(void *ctx)
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(ctx);
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid * aes_decrypt_init(const u8 *key, size_t len)
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	AES_KEY *ak;
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ak = os_malloc(sizeof(*ak));
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ak == NULL)
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (AES_set_decrypt_key(key, 8 * len, ak) < 0) {
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(ak);
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ak;
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	AES_decrypt(crypt, plain, ctx);
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid aes_decrypt_deinit(void *ctx)
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(ctx);
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_mod_exp(const u8 *base, size_t base_len,
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   const u8 *power, size_t power_len,
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   const u8 *modulus, size_t modulus_len,
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   u8 *result, size_t *result_len)
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result;
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret = -1;
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BN_CTX *ctx;
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx = BN_CTX_new();
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ctx == NULL)
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bn_base = BN_bin2bn(base, base_len, NULL);
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bn_exp = BN_bin2bn(power, power_len, NULL);
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bn_modulus = BN_bin2bn(modulus, modulus_len, NULL);
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bn_result = BN_new();
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    bn_result == NULL)
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		goto error;
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1)
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		goto error;
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*result_len = BN_bn2bin(bn_result, result);
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = 0;
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidterror:
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BN_free(bn_base);
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BN_free(bn_exp);
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BN_free(bn_modulus);
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BN_free(bn_result);
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BN_CTX_free(ctx);
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_cipher {
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	EVP_CIPHER_CTX enc;
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	EVP_CIPHER_CTX dec;
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  const u8 *iv, const u8 *key,
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  size_t key_len)
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct crypto_cipher *ctx;
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const EVP_CIPHER *cipher;
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ctx == NULL)
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (alg) {
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef OPENSSL_NO_RC4
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_RC4:
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		cipher = EVP_rc4();
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* OPENSSL_NO_RC4 */
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef OPENSSL_NO_AES
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_AES:
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		switch (key_len) {
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		case 16:
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			cipher = EVP_aes_128_cbc();
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		case 24:
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			cipher = EVP_aes_192_cbc();
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		case 32:
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			cipher = EVP_aes_256_cbc();
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		default:
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(ctx);
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return NULL;
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* OPENSSL_NO_AES */
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef OPENSSL_NO_DES
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_3DES:
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		cipher = EVP_des_ede3_cbc();
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_DES:
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		cipher = EVP_des_cbc();
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* OPENSSL_NO_DES */
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef OPENSSL_NO_RC2
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_RC2:
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		cipher = EVP_rc2_ecb();
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* OPENSSL_NO_RC2 */
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(ctx);
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	EVP_CIPHER_CTX_init(&ctx->enc);
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	EVP_CIPHER_CTX_set_padding(&ctx->enc, 0);
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) ||
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) ||
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, key, iv)) {
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		EVP_CIPHER_CTX_cleanup(&ctx->enc);
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(ctx);
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	EVP_CIPHER_CTX_init(&ctx->dec);
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	EVP_CIPHER_CTX_set_padding(&ctx->dec, 0);
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) ||
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) ||
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, key, iv)) {
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		EVP_CIPHER_CTX_cleanup(&ctx->enc);
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		EVP_CIPHER_CTX_cleanup(&ctx->dec);
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(ctx);
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ctx;
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			  u8 *crypt, size_t len)
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int outl;
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len))
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			  u8 *plain, size_t len)
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int outl;
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	outl = len;
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len))
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid crypto_cipher_deinit(struct crypto_cipher *ctx)
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	EVP_CIPHER_CTX_cleanup(&ctx->enc);
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	EVP_CIPHER_CTX_cleanup(&ctx->dec);
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(ctx);
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
361