Changeset 1500 for pjproject/trunk/pjsip/src/pjsip/sip_auth_aka.c
- Timestamp:
- Oct 15, 2007 7:04:59 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsip/sip_auth_aka.c
r1492 r1500 21 21 #include <pjlib-util/base64.h> 22 22 #include <pjlib-util/md5.h> 23 #include <pjlib-util/hmac_md5.h> 23 24 #include <pj/assert.h> 24 25 #include <pj/log.h> … … 26 27 #include <pj/string.h> 27 28 28 #if PJSIP_HAS_DIGEST_AKA V1_AUTH29 #if PJSIP_HAS_DIGEST_AKA_AUTH 29 30 30 31 #include "../../third_party/milenage/milenage.h" … … 33 34 * Create MD5-AKA1 digest response. 34 35 */ 35 PJ_DEF(pj_status_t) pjsip_auth_create_akav1( pj_pool_t *pool, 36 PJ_DEF(pj_status_t) pjsip_auth_create_aka_response( 37 pj_pool_t *pool, 36 38 const pjsip_digest_challenge*chal, 37 39 const pjsip_cred_info *cred, … … 40 42 { 41 43 pj_str_t nonce_bin; 42 pj_uint8_t *chal_rand, *chal_autn, *chal_mac; 44 int aka_version; 45 const pj_str_t pjsip_AKAv1_MD5 = { "AKAv1-MD5", 9 }; 46 const pj_str_t pjsip_AKAv2_MD5 = { "AKAv2-MD5", 9 }; 47 pj_uint8_t *chal_rand, *chal_sqnxoraka, *chal_mac; 48 pj_uint8_t k[PJSIP_AKA_KLEN]; 49 pj_uint8_t op[PJSIP_AKA_OPLEN]; 50 pj_uint8_t amf[PJSIP_AKA_AMFLEN]; 43 51 pj_uint8_t res[PJSIP_AKA_RESLEN]; 44 52 pj_uint8_t ck[PJSIP_AKA_CKLEN]; 45 53 pj_uint8_t ik[PJSIP_AKA_IKLEN]; 46 54 pj_uint8_t ak[PJSIP_AKA_AKLEN]; 47 pj_uint8_t sqn[PJSIP_AKA_ AUTNLEN];55 pj_uint8_t sqn[PJSIP_AKA_SQNLEN]; 48 56 pj_uint8_t xmac[PJSIP_AKA_MACLEN]; 49 57 pjsip_cred_info aka_cred; … … 52 60 53 61 /* Check the algorithm is supported. */ 54 if (pj_stricmp2(&chal->algorithm, "md5") == 0) { 62 if (chal->algorithm.slen==0 || pj_stricmp2(&chal->algorithm, "md5") == 0) { 63 /* 64 * A normal MD5 authentication is requested. Fallbackt to the usual 65 * MD5 digest creation. 66 */ 55 67 pjsip_auth_create_digest(&auth->response, &auth->nonce, &auth->nc, 56 68 &auth->cnonce, &auth->qop, &auth->uri, … … 58 70 return PJ_SUCCESS; 59 71 60 } else if (pj_stricmp2(&chal->algorithm, "AKAv1-MD5") != 0) { 72 } else if (pj_stricmp(&chal->algorithm, &pjsip_AKAv1_MD5) == 0) { 73 /* 74 * AKA version 1 is requested. 75 */ 76 aka_version = 1; 77 78 } else if (pj_stricmp(&chal->algorithm, &pjsip_AKAv2_MD5) == 0) { 79 /* 80 * AKA version 2 is requested. 81 */ 82 aka_version = 2; 83 84 } else { 61 85 /* Unsupported algorithm */ 62 86 return PJSIP_EINVALIDALGORITHM; … … 71 95 return PJSIP_EAUTHINNONCE; 72 96 73 if (nonce_bin.slen < PJSIP_AKA_RANDLEN + PJSIP_AKA_AUTNLEN + PJSIP_AKA_MACLEN)97 if (nonce_bin.slen < PJSIP_AKA_RANDLEN + PJSIP_AKA_AUTNLEN) 74 98 return PJSIP_EAUTHINNONCE; 75 99 76 100 /* Get RAND, AUTN, and MAC */ 77 chal_rand = (pj_uint8_t*) (nonce_bin.ptr + 0); 78 chal_autn = (pj_uint8_t*) (nonce_bin.ptr + PJSIP_AKA_RANDLEN); 79 chal_mac = (pj_uint8_t*) (nonce_bin.ptr + PJSIP_AKA_RANDLEN + PJSIP_AKA_AUTNLEN); 101 chal_rand = (pj_uint8_t*)(nonce_bin.ptr + 0); 102 chal_sqnxoraka = (pj_uint8_t*) (nonce_bin.ptr + PJSIP_AKA_RANDLEN); 103 chal_mac = (pj_uint8_t*) (nonce_bin.ptr + PJSIP_AKA_RANDLEN + 104 PJSIP_AKA_SQNLEN + PJSIP_AKA_AMFLEN); 80 105 81 /* Verify credential */ 82 PJ_ASSERT_RETURN(cred->ext.aka.k.slen == PJSIP_AKA_KLEN, PJSIP_EAUTHINAKACRED); 83 PJ_ASSERT_RETURN(cred->ext.aka.op.slen == PJSIP_AKA_OPLEN, PJSIP_EAUTHINAKACRED); 106 /* Copy k. op, and amf */ 107 pj_bzero(k, sizeof(k)); 108 pj_bzero(op, sizeof(op)); 109 pj_bzero(amf, sizeof(amf)); 110 111 if (cred->ext.aka.k.slen) 112 pj_memcpy(k, cred->ext.aka.k.ptr, cred->ext.aka.k.slen); 113 if (cred->ext.aka.op.slen) 114 pj_memcpy(op, cred->ext.aka.op.ptr, cred->ext.aka.op.slen); 115 if (cred->ext.aka.amf.slen) 116 pj_memcpy(amf, cred->ext.aka.amf.ptr, cred->ext.aka.amf.slen); 84 117 85 118 /* Given key K and random challenge RAND, compute response RES, 86 119 * confidentiality key CK, integrity key IK and anonymity key AK. 87 120 */ 88 f2345((pj_uint8_t*)cred->ext.aka.k.ptr, 89 chal_rand, 90 res, ck, ik, ak, 91 (pj_uint8_t*)cred->ext.aka.op.ptr); 121 f2345(k, chal_rand, res, ck, ik, ak, op); 92 122 93 123 /* Compute sequence number SQN */ 94 for (i=0; i<PJSIP_AKA_AUTNLEN; ++i) 95 sqn[i] = (pj_uint8_t) (chal_autn[i] ^ ak[i]); 96 97 /* Compute XMAC */ 98 f1((pj_uint8_t*)cred->ext.aka.k.ptr, chal_rand, sqn, 99 (pj_uint8_t*)cred->ext.aka.amf.ptr, xmac, 100 (pj_uint8_t*)cred->ext.aka.op.ptr); 124 for (i=0; i<PJSIP_AKA_SQNLEN; ++i) 125 sqn[i] = (pj_uint8_t) (chal_sqnxoraka[i] ^ ak[i]); 101 126 102 127 /* Verify MAC in the challenge */ 128 /* Compute XMAC */ 129 f1(k, chal_rand, sqn, amf, xmac, op); 130 103 131 if (pj_memcmp(chal_mac, xmac, PJSIP_AKA_MACLEN) != 0) { 104 132 return PJSIP_EAUTHINNONCE; … … 110 138 pj_memcpy(&aka_cred, cred, sizeof(aka_cred)); 111 139 aka_cred.data_type = PJSIP_CRED_DATA_PLAIN_PASSWD; 112 aka_cred.data.ptr = (char*)res;113 aka_cred.data.slen = PJSIP_AKA_RESLEN;114 140 115 141 /* Create a response */ 116 pjsip_auth_create_digest(&auth->response, &chal->nonce, 117 &auth->nc, &auth->cnonce, &auth->qop, &auth->uri, 118 &chal->realm, &aka_cred, method); 142 if (aka_version == 1) { 143 /* 144 * For AKAv1, the password is RES 145 */ 146 aka_cred.data.ptr = (char*)res; 147 aka_cred.data.slen = PJSIP_AKA_RESLEN; 148 149 pjsip_auth_create_digest(&auth->response, &chal->nonce, 150 &auth->nc, &auth->cnonce, &auth->qop, 151 &auth->uri, &chal->realm, &aka_cred, method); 152 153 } else if (aka_version == 2) { 154 /* 155 * For AKAv2, password is base64 encoded [1] parameters: 156 * PRF(RES||IK||CK,"http-digest-akav2-password") 157 * 158 * The pseudo-random function (PRF) is HMAC-MD5 in this case. 159 */ 160 pj_hmac_md5_context ctx; 161 pj_uint8_t hmac_digest[16]; 162 char hmac_digest64[24]; 163 int out_len; 164 165 pj_hmac_md5_init(&ctx, (pj_uint8_t*)"http-digest-akav2-password", 26); 166 pj_hmac_md5_update(&ctx, res, PJSIP_AKA_RESLEN); 167 pj_hmac_md5_update(&ctx, ik, PJSIP_AKA_IKLEN); 168 pj_hmac_md5_update(&ctx, ck, PJSIP_AKA_CKLEN); 169 pj_hmac_md5_final(&ctx, hmac_digest); 170 171 out_len = sizeof(hmac_digest64); 172 status = pj_base64_encode(hmac_digest, 16, hmac_digest64, &out_len); 173 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 174 175 aka_cred.data.ptr = hmac_digest64; 176 aka_cred.data.slen = out_len; 177 178 pjsip_auth_create_digest(&auth->response, &chal->nonce, 179 &auth->nc, &auth->cnonce, &auth->qop, 180 &auth->uri, &chal->realm, &aka_cred, method); 181 182 } else { 183 pj_assert(!"Bug!"); 184 return PJ_EBUG; 185 } 119 186 120 187 /* Done */ … … 123 190 124 191 125 #endif /* PJSIP_HAS_DIGEST_AKA V1_AUTH */192 #endif /* PJSIP_HAS_DIGEST_AKA_AUTH */ 126 193
Note: See TracChangeset
for help on using the changeset viewer.