blob: 70e2cf646796016c94e29fdf424b7e0b7c4831b7 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lamaa8e15a2014-02-11 23:30:06 -08002 * Copyright (c) 2012-2013 Qualcomm Atheros, Inc.
3 * All Rights Reserved.
4 * Qualcomm Atheros Confidential and Proprietary.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08005 */
6/*
Jeff Johnson295189b2012-06-20 16:38:30 -07007 * Woodside Networks, Inc proprietary. All rights reserved.
8 * $File: //depot/software/projects/feature_branches/gen5_phase1/os/linux/classic/ap/apps/ssm/auth8021x/ani8021xPrf.c $
9 *
10 * Contains definitions for routines to calculate the 802.11i PRF
11 * functions.
12 *
13 * Author: Mayank D. Upadhyay
14 * Date: 19-March-2003
15 * History:-
16 * Date Modified by Modification Information
17 * ------------------------------------------------------
18 */
19
20/*#include <assert.h>
21#include <stdlib.h>
22#include <aniSsmSha1.h>
23*/
24#include "vos_utils.h"
25#include "vos_memory.h"
26#include "bapRsn8021xPrf.h"
27#include "bapRsnErrors.h"
28//#include "ani8021xUtils.h"
29
30#define AAG_PTK_PRF_ADD_PARAM 159
31#define AAG_PTK_PRF_DIV_PARAM 160
32
33#define AAG_PTK_PRF_CONST "Pairwise key expansion"
34#define AAG_PTK_PRF_CONST_LEN 22
35
36#define AAG_PTK_PRF_LM_POS 0
37#define AAG_PTK_PRF_HM_POS 6
38#define AAG_PTK_PRF_LN_POS 12
Madan Mohan Koyyalamudia53c4dc2012-11-13 10:35:42 -080039#define AAG_PTK_PRF_HN_POS (AAG_PTK_PRF_LN_POS + ANI_EAPOL_KEY_RSN_NONCE_SIZE)
Jeff Johnson295189b2012-06-20 16:38:30 -070040
Madan Mohan Koyyalamudia53c4dc2012-11-13 10:35:42 -080041#define AAG_PTK_PRF_TEXT_LEN (AAG_PTK_PRF_HN_POS + ANI_EAPOL_KEY_RSN_NONCE_SIZE)
Jeff Johnson295189b2012-06-20 16:38:30 -070042
43#define AAG_GTK_PRF_CONST "Group key expansion"
44#define AAG_GTK_PRF_CONST_LEN 19
45
46#define AAG_GTK_PRF_MAC_POS 0
47#define AAG_GTK_PRF_NONCE_POS 6
48
Madan Mohan Koyyalamudia53c4dc2012-11-13 10:35:42 -080049#define AAG_GTK_PRF_TEXT_LEN (AAG_GTK_PRF_NONCE_POS + ANI_EAPOL_KEY_RSN_NONCE_SIZE)
Jeff Johnson295189b2012-06-20 16:38:30 -070050
51/**
52 * aagGetKeyMaterialLen
53 *
54 * Returns the number of bytes of the PTK that have to be provided to
55 * the MAC layer for a given cipher type.
56 *
57 * @param cipherType the cipher-type
58 *
59 * @return the number of bytes of key material for this cipher type,
60 * or 0 for invalid cipher types.
61 */
62int
63aagGetKeyMaterialLen(eCsrEncryptionType cipherType)
64{
65 switch (cipherType) {
66 case eCSR_ENCRYPT_TYPE_AES:
67 return AAG_RSN_KEY_MATERIAL_LEN_CCMP;
68 break;
69 default:
70 return 0;
71 break;
72 };
73}
74
75/**
76 * aagPtkPrf
77 *
78 * The PRF used for calculating the pairwise temporal key under IEEE
79 * 802.11i.
80 *
81 * @param result a fixed size array where the outputis stored. Should
82 * have enough place for the SHA-1 overflow.
83 * @param prfLen the number of BITS desired from the PRF result
84 * @param pmk the pairwise master-key
85 * @param authAddr the MAC address of the authenticator
86 * @param suppAddr the MAC address of the supplicant
87 * @param aNonce the nonce generated by the authenticator
88 * @param sNonce the nonce generated by the supplicant
89 *
90 * @return ANI_OK if the operation succeeds
91 */
92int
93aagPtkPrf(v_U32_t cryptHandle,
94 v_U8_t result[AAG_PRF_MAX_OUTPUT_SIZE],
95 v_U32_t prfLen,
96 tAniPacket *pmk,
97 tAniMacAddr authAddr,
98 tAniMacAddr suppAddr,
99 v_U8_t aNonce[ANI_EAPOL_KEY_RSN_NONCE_SIZE],
100 v_U8_t sNonce[ANI_EAPOL_KEY_RSN_NONCE_SIZE])
101{
102 v_U8_t *lowMac;
103 v_U8_t *highMac;
104 v_U8_t *lowNonce;
105 v_U8_t *highNonce;
106
107 v_U8_t *keyBytes;
108 int keyLen;
109
110 v_U8_t text[AAG_PTK_PRF_TEXT_LEN];
111
112 //Cannot use voss function here because vos_mem_compare doesn't tell whihc is larger
113 if (vos_mem_compare2(authAddr, suppAddr, sizeof(tAniMacAddr)) < 0) {
114 lowMac = authAddr;
115 highMac = suppAddr;
116 } else {
117 lowMac = suppAddr;
118 highMac = authAddr;
119 }
120
121 if (vos_mem_compare2(aNonce, sNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE) < 0) {
122 lowNonce = aNonce;
123 highNonce = sNonce;
124 } else {
125 lowNonce = sNonce;
126 highNonce = aNonce;
127 }
128
129 vos_mem_copy(text + AAG_PTK_PRF_LM_POS, lowMac, sizeof(tAniMacAddr));
130 vos_mem_copy(text + AAG_PTK_PRF_HM_POS, highMac, sizeof(tAniMacAddr));
131 vos_mem_copy(text + AAG_PTK_PRF_LN_POS, lowNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE);
132 vos_mem_copy(text + AAG_PTK_PRF_HN_POS, highNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE);
133
134 keyLen = aniAsfPacketGetBytes(pmk, &keyBytes);
135 if( !ANI_IS_STATUS_SUCCESS( keyLen ) )
136 {
137 return keyLen;
138 }
139
140 return aagPrf(cryptHandle,
141 result,
142 keyBytes, keyLen,
143 (v_U8_t *)AAG_PTK_PRF_CONST, AAG_PTK_PRF_CONST_LEN,
144 text, sizeof(text),
145 prfLen);
146}
147
148/**
149 * aagGtkPrf
150 *
151 * The PRF used for calculating the group temporal key under IEEE
152 * 802.11i.
153 *
154 * @param result a fixed size array where the outputis stored. Should
155 * have enough place for the SHA-1 overflow.
156 * @param prfLen the number of BITS desired from the PRF result
157 * @param gmk the group master-key
158 * @param authAddr the MAC address of the authenticator
159 * @param gNonce the nonce generated by the authenticator for this purpose
160 *
161 * @return ANI_OK if the operation succeeds
162 */
163int
164aagGtkPrf(v_U32_t cryptHandle,
165 v_U8_t result[AAG_PRF_MAX_OUTPUT_SIZE],
166 v_U32_t prfLen,
167 v_U8_t gmk[AAG_RSN_GMK_SIZE],
168 tAniMacAddr authAddr,
169 v_U8_t gNonce[ANI_EAPOL_KEY_RSN_NONCE_SIZE])
170{
171 v_U8_t text[AAG_GTK_PRF_TEXT_LEN];
172
173 vos_mem_copy(text + AAG_GTK_PRF_MAC_POS, authAddr, sizeof(tAniMacAddr));
174 vos_mem_copy(text + AAG_GTK_PRF_NONCE_POS, gNonce, ANI_EAPOL_KEY_RSN_NONCE_SIZE);
175
176 return aagPrf(cryptHandle,
177 result,
178 gmk, AAG_RSN_GMK_SIZE,
179 (v_U8_t *)AAG_GTK_PRF_CONST, AAG_GTK_PRF_CONST_LEN,
180 text, sizeof(text),
181 prfLen);
182
183}
184
185/**
186 * aagPrf
187 *
188 * The raw PRF function that is used in IEEE 802.11i.
189 *
190 * @param result a fixed size array where the outputis stored. Should
191 * have enough place for the SHA-1 overflow.
192 * @param key the key to use in the PRF
193 * @param keyLen the length of the key
194 * @param a the parameter A which is usually a unique label
195 * @param aLen the length of the parameter A
196 * @ param b the parameter B
197 * @param bLen the length of parameter B
198 * @param prfLen the number to BITS desired from the PRF result
199 *
200 * @return ANI_OK if the operation succeeds
201 */
202int
203aagPrf(v_U32_t cryptHandle,
204 v_U8_t result[AAG_PRF_MAX_OUTPUT_SIZE],
205 v_U8_t *key, v_U8_t keyLen,
206 v_U8_t *a, v_U8_t aLen,
207 v_U8_t *b, v_U8_t bLen,
208 v_U32_t prfLen)
209{
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700210 static v_U8_t y;
Jeff Johnson295189b2012-06-20 16:38:30 -0700211
212 v_U8_t *hmacText = NULL;
213 v_U8_t *resultOffset = result;
214 int numLoops;
215 int loopCtrPos;
216 int i, retVal=0;
217
218 hmacText = vos_mem_malloc( aLen + bLen + 2 );
219 if( NULL == hmacText )
220 {
221 return ANI_E_NULL_VALUE;
222 }
223
224 vos_mem_copy(hmacText + 0, a, aLen);
225 hmacText[aLen] = y;
226 vos_mem_copy(hmacText + aLen + 1, b, bLen);
227 loopCtrPos = aLen + 1 + bLen;
228
229 numLoops = prfLen + AAG_PTK_PRF_ADD_PARAM;
230 numLoops /= AAG_PTK_PRF_DIV_PARAM;
231
232 for (i = 0; i < numLoops; i++)
233 {
234 VOS_ASSERT((resultOffset - result + VOS_DIGEST_SHA1_SIZE)
235 <= AAG_PRF_MAX_OUTPUT_SIZE);
236 hmacText[loopCtrPos] = i;
237 if( VOS_IS_STATUS_SUCCESS( vos_sha1_hmac_str(cryptHandle, hmacText, loopCtrPos + 1, key, keyLen, resultOffset) ) )
238 {
239 resultOffset += VOS_DIGEST_SHA1_SIZE;
240 retVal = ANI_OK;
241 }
242 else
243 {
244 retVal = ANI_ERROR;
245 }
246 }
247
248 vos_mem_free(hmacText);
249
250 return retVal;
251}
252