1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant / Crypto wrapper for internal crypto implementation
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2006-2007, 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
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "crypto.h"
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "md5.h"
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "sha1.h"
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "rc4.h"
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "aes.h"
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "tls/rsa.h"
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "tls/bignum.h"
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "tls/asn1.h"
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CRYPTO_INTERNAL
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_TLS_INTERNAL
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* from des.c */
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct des3_key_s {
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u32 ek[3][32];
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u32 dk[3][32];
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid des3_key_setup(const u8 *key, struct des3_key_s *dkey);
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt);
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain);
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct MD5Context {
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u32 buf[4];
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u32 bits[2];
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 in[64];
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct SHA1Context {
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u32 state[5];
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u32 count[2];
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	unsigned char buffer[64];
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_hash {
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	enum crypto_hash_alg alg;
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	union {
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		struct MD5Context md5;
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		struct SHA1Context sha1;
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} u;
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 key[64];
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t key_len;
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				      size_t key_len)
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct crypto_hash *ctx;
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 k_pad[64];
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 tk[20];
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t i;
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ctx == NULL)
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->alg = alg;
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (alg) {
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_MD5:
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5Init(&ctx->u.md5);
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_SHA1:
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1Init(&ctx->u.sha1);
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_MD5:
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (key_len > sizeof(k_pad)) {
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			MD5Init(&ctx->u.md5);
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			MD5Update(&ctx->u.md5, key, key_len);
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			MD5Final(tk, &ctx->u.md5);
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			key = tk;
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			key_len = 16;
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(ctx->key, key, key_len);
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctx->key_len = key_len;
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(k_pad, key, key_len);
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (i = 0; i < sizeof(k_pad); i++)
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			k_pad[i] ^= 0x36;
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5Init(&ctx->u.md5);
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_SHA1:
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (key_len > sizeof(k_pad)) {
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SHA1Init(&ctx->u.sha1);
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SHA1Update(&ctx->u.sha1, key, key_len);
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			SHA1Final(tk, &ctx->u.sha1);
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			key = tk;
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			key_len = 20;
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(ctx->key, key, key_len);
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctx->key_len = key_len;
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(k_pad, key, key_len);
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (i = 0; i < sizeof(k_pad); i++)
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			k_pad[i] ^= 0x36;
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1Init(&ctx->u.sha1);
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(ctx);
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ctx;
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ctx == NULL)
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (ctx->alg) {
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_MD5:
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_MD5:
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5Update(&ctx->u.md5, data, len);
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_SHA1:
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_SHA1:
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1Update(&ctx->u.sha1, data, len);
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 k_pad[64];
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t i;
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ctx == NULL)
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -2;
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (mac == NULL || len == NULL) {
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(ctx);
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (ctx->alg) {
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_MD5:
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*len < 16) {
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*len = 16;
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(ctx);
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*len = 16;
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5Final(mac, &ctx->u.md5);
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_SHA1:
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*len < 20) {
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*len = 20;
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(ctx);
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*len = 20;
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1Final(mac, &ctx->u.sha1);
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_MD5:
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*len < 16) {
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*len = 16;
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(ctx);
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*len = 16;
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5Final(mac, &ctx->u.md5);
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(k_pad, ctx->key, ctx->key_len);
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memset(k_pad + ctx->key_len, 0,
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			  sizeof(k_pad) - ctx->key_len);
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (i = 0; i < sizeof(k_pad); i++)
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			k_pad[i] ^= 0x5c;
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5Init(&ctx->u.md5);
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5Update(&ctx->u.md5, mac, 16);
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		MD5Final(mac, &ctx->u.md5);
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_HASH_ALG_HMAC_SHA1:
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (*len < 20) {
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			*len = 20;
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(ctx);
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*len = 20;
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1Final(mac, &ctx->u.sha1);
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(k_pad, ctx->key, ctx->key_len);
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memset(k_pad + ctx->key_len, 0,
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			  sizeof(k_pad) - ctx->key_len);
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (i = 0; i < sizeof(k_pad); i++)
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			k_pad[i] ^= 0x5c;
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1Init(&ctx->u.sha1);
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1Update(&ctx->u.sha1, mac, 20);
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SHA1Final(mac, &ctx->u.sha1);
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(ctx);
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_cipher {
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	enum crypto_cipher_alg alg;
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	union {
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		struct {
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			size_t used_bytes;
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			u8 key[16];
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			size_t keylen;
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} rc4;
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		struct {
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			u8 cbc[32];
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			size_t block_size;
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			void *ctx_enc;
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			void *ctx_dec;
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} aes;
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		struct {
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			struct des3_key_s key;
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			u8 cbc[8];
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} des3;
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} u;
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  const u8 *iv, const u8 *key,
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  size_t key_len)
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct crypto_cipher *ctx;
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx = os_zalloc(sizeof(*ctx));
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ctx == NULL)
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ctx->alg = alg;
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (alg) {
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_RC4:
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (key_len > sizeof(ctx->u.rc4.key)) {
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(ctx);
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return NULL;
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctx->u.rc4.keylen = key_len;
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(ctx->u.rc4.key, key, key_len);
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_AES:
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (key_len > sizeof(ctx->u.aes.cbc)) {
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(ctx);
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return NULL;
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len);
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ctx->u.aes.ctx_enc == NULL) {
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(ctx);
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return NULL;
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len);
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ctx->u.aes.ctx_dec == NULL) {
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			aes_encrypt_deinit(ctx->u.aes.ctx_enc);
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(ctx);
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return NULL;
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctx->u.aes.block_size = key_len;
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size);
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_3DES:
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (key_len != 24) {
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(ctx);
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return NULL;
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		des3_key_setup(key, &ctx->u.des3.key);
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(ctx->u.des3.cbc, iv, 8);
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(ctx);
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ctx;
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			  u8 *crypt, size_t len)
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t i, j, blocks;
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (ctx->alg) {
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_RC4:
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (plain != crypt)
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(crypt, plain, len);
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			 ctx->u.rc4.used_bytes, crypt, len);
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctx->u.rc4.used_bytes += len;
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_AES:
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (len % ctx->u.aes.block_size)
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		blocks = len / ctx->u.aes.block_size;
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (i = 0; i < blocks; i++) {
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			for (j = 0; j < ctx->u.aes.block_size; j++)
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				ctx->u.aes.cbc[j] ^= plain[j];
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc,
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    ctx->u.aes.cbc);
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(crypt, ctx->u.aes.cbc,
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  ctx->u.aes.block_size);
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			plain += ctx->u.aes.block_size;
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			crypt += ctx->u.aes.block_size;
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_3DES:
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (len % 8)
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		blocks = len / 8;
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (i = 0; i < blocks; i++) {
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			for (j = 0; j < 8; j++)
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				ctx->u.des3.cbc[j] ^= plain[j];
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key,
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				     ctx->u.des3.cbc);
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(crypt, ctx->u.des3.cbc, 8);
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			plain += 8;
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			crypt += 8;
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			  u8 *plain, size_t len)
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t i, j, blocks;
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 tmp[32];
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (ctx->alg) {
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_RC4:
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (plain != crypt)
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(plain, crypt, len);
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			 ctx->u.rc4.used_bytes, plain, len);
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ctx->u.rc4.used_bytes += len;
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_AES:
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (len % ctx->u.aes.block_size)
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		blocks = len / ctx->u.aes.block_size;
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (i = 0; i < blocks; i++) {
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(tmp, crypt, ctx->u.aes.block_size);
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain);
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			for (j = 0; j < ctx->u.aes.block_size; j++)
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				plain[j] ^= ctx->u.aes.cbc[j];
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size);
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			plain += ctx->u.aes.block_size;
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			crypt += ctx->u.aes.block_size;
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_3DES:
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (len % 8)
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		blocks = len / 8;
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		for (i = 0; i < blocks; i++) {
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(tmp, crypt, 8);
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			des3_decrypt(crypt, &ctx->u.des3.key, plain);
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			for (j = 0; j < 8; j++)
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				plain[j] ^= ctx->u.des3.cbc[j];
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_memcpy(ctx->u.des3.cbc, tmp, 8);
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			plain += 8;
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			crypt += 8;
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid crypto_cipher_deinit(struct crypto_cipher *ctx)
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (ctx->alg) {
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_AES:
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		aes_encrypt_deinit(ctx->u.aes.ctx_enc);
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		aes_decrypt_deinit(ctx->u.aes.ctx_dec);
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case CRYPTO_CIPHER_ALG_3DES:
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(ctx);
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* Dummy structures; these are just typecast to struct crypto_rsa_key */
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_public_key;
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_private_key;
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return (struct crypto_public_key *)
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		crypto_rsa_import_public_key(key, len);
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
438dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt#ifdef EAP_TLS_FUNCS
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct crypto_private_key *
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtcrypto_pkcs8_key_import(const u8 *buf, size_t len)
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct asn1_hdr hdr;
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const u8 *pos, *end;
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct bignum *zero;
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct asn1_oid oid;
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char obuf[80];
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* PKCS #8, Chapter 6 */
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* PrivateKeyInfo ::= SEQUENCE */
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (asn1_get_next(buf, len, &hdr) < 0 ||
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    hdr.tag != ASN1_TAG_SEQUENCE) {
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "header (SEQUENCE); assume PKCS #8 not used");
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = hdr.payload;
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	end = pos + hdr.length;
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* version Version (Version ::= INTEGER) */
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found "
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "class %d tag 0x%x; assume PKCS #8 not used",
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   hdr.class, hdr.tag);
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	zero = bignum_init();
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (zero == NULL)
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		bignum_deinit(zero);
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = hdr.payload + hdr.length;
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (bignum_cmp_d(zero, 0) != 0) {
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "beginning of private key; not found; assume "
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "PKCS #8 not used");
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		bignum_deinit(zero);
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bignum_deinit(zero);
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (asn1_get_next(pos, len, &hdr) < 0 ||
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    hdr.tag != ASN1_TAG_SEQUENCE) {
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "(AlgorithmIdentifier) - found class %d tag 0x%x; "
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "assume PKCS #8 not used",
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   hdr.class, hdr.tag);
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "(algorithm); assume PKCS #8 not used");
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (oid.len != 7 ||
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    oid.oid[0] != 1 /* iso */ ||
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    oid.oid[1] != 2 /* member-body */ ||
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    oid.oid[2] != 840 /* us */ ||
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    oid.oid[3] != 113549 /* rsadsi */ ||
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    oid.oid[4] != 1 /* pkcs */ ||
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    oid.oid[5] != 1 /* pkcs-1 */ ||
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    oid.oid[6] != 1 /* rsaEncryption */) {
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "algorithm %s", obuf);
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = hdr.payload + hdr.length;
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    hdr.tag != ASN1_TAG_OCTETSTRING) {
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "(privateKey) - found class %d tag 0x%x",
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   hdr.class, hdr.tag);
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return (struct crypto_private_key *)
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		crypto_rsa_import_private_key(hdr.payload, hdr.length);
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
540dde787cc314cd04caa4ea5f031cc8a02495ca513Dmitry Shmidt#endif /* EAP_TLS_FUNCS */
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_private_key * crypto_private_key_import(const u8 *key,
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						      size_t len)
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct crypto_private_key *res;
547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* First, check for possible PKCS #8 encoding */
549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = crypto_pkcs8_key_import(key, len);
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res)
551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return res;
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private "
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "key");
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return (struct crypto_private_key *)
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		crypto_rsa_import_private_key(key, len);
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						       size_t len)
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* No X.509 support in crypto_internal.c */
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return NULL;
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   const u8 *in, size_t inlen,
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					   u8 *out, size_t *outlen)
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t ps_len;
574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 *pos;
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * PKCS #1 v1.5, 8.1:
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 *
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * EB = 00 || BT || PS || 00 || D
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * PS = k-3-||D||; at least eight octets
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * k = length of modulus in octets (modlen)
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   __func__, (unsigned long) modlen,
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned long) *outlen,
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned long) inlen);
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = out;
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*pos++ = 0x00;
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*pos++ = block_type; /* BT */
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ps_len = modlen - inlen - 3;
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	switch (block_type) {
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case 0:
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memset(pos, 0x00, ps_len);
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos += ps_len;
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case 1:
605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memset(pos, 0xff, ps_len);
606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos += ps_len;
607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	case 2:
609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (os_get_random(pos, ps_len) < 0) {
610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "random data for PS", __func__);
612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		while (ps_len--) {
615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (*pos == 0x00)
616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				*pos = 0x01;
617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			pos++;
618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		break;
620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	default:
621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "%d", __func__, block_type);
623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*pos++ = 0x00;
626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(pos, in, inlen); /* D */
627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int crypto_rsa_encrypt_pkcs1(int block_type, struct crypto_rsa_key *key,
633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    int use_private,
634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    const u8 *in, size_t inlen,
635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    u8 *out, size_t *outlen)
636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t modlen;
638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	modlen = crypto_rsa_get_modulus_len(key);
640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					    out, outlen) < 0)
643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private);
646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					const u8 *in, size_t inlen,
651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					u8 *out, size_t *outlen)
652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return crypto_rsa_encrypt_pkcs1(2, (struct crypto_rsa_key *) key,
654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					0, in, inlen, out, outlen);
655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key,
659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					 const u8 *in, size_t inlen,
660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					 u8 *out, size_t *outlen)
661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct crypto_rsa_key *rkey = (struct crypto_rsa_key *) key;
663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int res;
664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 *pos, *end;
665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	res = crypto_rsa_exptmod(in, inlen, out, outlen, rkey, 1);
667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (res)
668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return res;
669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (*outlen < 2 || out[0] != 0 || out[1] != 2)
671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Skip PS (pseudorandom non-zero octets) */
674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = out + 2;
675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	end = out + *outlen;
676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	while (*pos && pos < end)
677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos++;
678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pos == end)
679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos++;
681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*outlen -= pos - out;
683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Strip PKCS #1 header */
685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memmove(out, pos, *outlen);
686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  const u8 *in, size_t inlen,
693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  u8 *out, size_t *outlen)
694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return crypto_rsa_encrypt_pkcs1(1, (struct crypto_rsa_key *) key,
696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					1, in, inlen, out, outlen);
697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid crypto_public_key_free(struct crypto_public_key *key)
701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	crypto_rsa_free((struct crypto_rsa_key *) key);
703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid crypto_private_key_free(struct crypto_private_key *key)
707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	crypto_rsa_free((struct crypto_rsa_key *) key);
709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    const u8 *crypt, size_t crypt_len,
714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    u8 *plain, size_t *plain_len)
715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t len;
717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	u8 *pos;
718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	len = *plain_len;
720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len,
721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       (struct crypto_rsa_key *) key, 0) < 0)
722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * PKCS #1 v1.5, 8.1:
726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 *
727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * EB = 00 || BT || PS || 00 || D
728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * BT = 00 or 01
729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01)
730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * k = length of modulus in octets
731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len < 3 + 8 + 16 /* min hash len */ ||
734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) {
735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "structure");
737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = plain + 3;
741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (plain[1] == 0x00) {
742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* BT = 00 */
743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (plain[2] != 0x00) {
744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "PS (BT=00)");
746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00)
749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			pos++;
750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	} else {
751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* BT = 01 */
752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (plain[2] != 0xff) {
753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "PS (BT=01)");
755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		while (pos < plain + len && *pos == 0xff)
758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			pos++;
759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pos - plain - 2 < 8) {
762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "padding");
765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "structure (2)");
771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos++;
774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	len -= pos - plain;
775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Strip PKCS #1 header */
777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memmove(plain, pos, len);
778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*plain_len = len;
779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_global_init(void)
785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid crypto_global_deinit(void)
791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_TLS_INTERNAL */
794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#if defined(EAP_FAST) || defined(CONFIG_WPS)
797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint crypto_mod_exp(const u8 *base, size_t base_len,
799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   const u8 *power, size_t power_len,
800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   const u8 *modulus, size_t modulus_len,
801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   u8 *result, size_t *result_len)
802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result;
804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret = -1;
805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bn_base = bignum_init();
807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bn_exp = bignum_init();
808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bn_modulus = bignum_init();
809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bn_result = bignum_init();
810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    bn_result == NULL)
813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		goto error;
814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 ||
816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 ||
817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0)
818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		goto error;
819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0)
821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		goto error;
822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = bignum_get_unsigned_bin(bn_result, result, result_len);
824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidterror:
826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bignum_deinit(bn_base);
827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bignum_deinit(bn_exp);
828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bignum_deinit(bn_modulus);
829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bignum_deinit(bn_result);
830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* EAP_FAST || CONFIG_WPS */
834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
836526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CRYPTO_INTERNAL */
837