Jeff Johnson | 295189b | 2012-06-20 16:38:30 -0700 | [diff] [blame] | 1 | /* |
Kiet Lam | aa8e15a | 2014-02-11 23:30:06 -0800 | [diff] [blame^] | 2 | * Copyright (c) 2012-2013 Qualcomm Atheros, Inc. |
| 3 | * All Rights Reserved. |
| 4 | * Qualcomm Atheros Confidential and Proprietary. |
Gopichand Nakkala | 92f07d8 | 2013-01-08 21:16:34 -0800 | [diff] [blame] | 5 | */ |
| 6 | /* |
Jeff Johnson | 295189b | 2012-06-20 16:38:30 -0700 | [diff] [blame] | 7 | * 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 Koyyalamudi | a53c4dc | 2012-11-13 10:35:42 -0800 | [diff] [blame] | 39 | #define AAG_PTK_PRF_HN_POS (AAG_PTK_PRF_LN_POS + ANI_EAPOL_KEY_RSN_NONCE_SIZE) |
Jeff Johnson | 295189b | 2012-06-20 16:38:30 -0700 | [diff] [blame] | 40 | |
Madan Mohan Koyyalamudi | a53c4dc | 2012-11-13 10:35:42 -0800 | [diff] [blame] | 41 | #define AAG_PTK_PRF_TEXT_LEN (AAG_PTK_PRF_HN_POS + ANI_EAPOL_KEY_RSN_NONCE_SIZE) |
Jeff Johnson | 295189b | 2012-06-20 16:38:30 -0700 | [diff] [blame] | 42 | |
| 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 Koyyalamudi | a53c4dc | 2012-11-13 10:35:42 -0800 | [diff] [blame] | 49 | #define AAG_GTK_PRF_TEXT_LEN (AAG_GTK_PRF_NONCE_POS + ANI_EAPOL_KEY_RSN_NONCE_SIZE) |
Jeff Johnson | 295189b | 2012-06-20 16:38:30 -0700 | [diff] [blame] | 50 | |
| 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 | */ |
| 62 | int |
| 63 | aagGetKeyMaterialLen(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 | */ |
| 92 | int |
| 93 | aagPtkPrf(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 | */ |
| 163 | int |
| 164 | aagGtkPrf(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 | */ |
| 202 | int |
| 203 | aagPrf(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 Koyyalamudi | dfd6aa8 | 2012-10-18 20:18:43 -0700 | [diff] [blame] | 210 | static v_U8_t y; |
Jeff Johnson | 295189b | 2012-06-20 16:38:30 -0700 | [diff] [blame] | 211 | |
| 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 | |