1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifdef __cplusplus 18 extern "C" { 19 #endif 20 21 /*======================================================================= 22 23 Header Name: syncmldm_security.c 24 25 General Description: This file contains definition of functions to 26 build the credentials with Basic, MD5 and 27 HMAC-MD5 and to generate the nonce string. 28 NOTE: All the user name/serverid and password are NULL terminated 29 strings. 30 =======================================================================*/ 31 32 #include "xpl_Time.h" 33 #include "dmStringUtil.h" 34 #include "dm_security.h" 35 #include "xpt-b64.h" /* To include base64Encode function */ 36 #include "md5.h" /* To include smlMD5Init, smlMD5Update and smlMD5Final functions */ 37 38 #ifdef PLATFORM_ANDROID 39 #include <sys/stat.h> /* include open and read functions */ 40 #include <fcntl.h> /* include O_RDONLY definition */ 41 #endif 42 43 /*======================================================================= 44 MACROS 45 =======================================================================*/ 46 47 #define MAXIMUM_SAVE_BYTES 4 /* This will be used in base64Encode function*/ 48 #define COLON_PLUS_NULL 2 49 #define SYNCML_DM_NEXT_BLOCK 1 50 51 extern void GetIMEI(char * str); 52 53 /*======================================================================= 54 LOCAL FUNCTION PROTOTYPES 55 =======================================================================*/ 56 57 /************************************************************************ 58 FUNCTION: get_pseudo_random 59 60 DESCRIPTION: Generates pseudo random bytes and stores them in the 61 input buffer in reverse order 62 63 ARGUMENTS PASSED: 64 65 UINT8 *buffer 66 - Buffer which will contain output pseudo random bytes 67 length 68 - Number of psuedo random bytes to be generated 69 70 71 RETURN VALUE: 72 void 73 74 PRE-CONDITIONS: 75 76 77 POST-CONDITIONS: 78 79 IMPORTANT NOTES: 80 None 81 ************************************************************************/ 82 static void get_pseudo_random(UINT8 *pbBuffer, UINT16 wLength) 83 { 84 #ifdef PLATFORM_ANDROID 85 /* Use /dev/urandom for secure PRNG. */ 86 int fd; 87 ssize_t count = 0; 88 while ((fd = open("/dev/urandom", O_RDONLY)) == -1) { 89 /* This open should always succeed; loop forever until it does. */ 90 } 91 while (count < wLength) { 92 int b = read(fd, &pbBuffer[count], wLength - count); 93 if (b == -1) { 94 /* Error: should never happen with /dev/urandom; try again. */ 95 } else { 96 count += b; 97 } 98 } 99 close(fd); 100 #else 101 /* Location of this function is 102 * /vobs/core_browser/code/cryptolib/src/rsa_msg_enc.c 103 */ 104 INT16 wCount = 0; 105 106 XPL_CLK_CLOCK_T t = XPL_CLK_GetClock(); 107 /* The current time is given as seed for generating 108 * pseudo random numbers */ 109 srand ((UINT32)t); 110 for (wCount = 0; wCount < wLength; wCount++) 111 { 112 pbBuffer[wCount] = (UINT8) rand (); 113 if (pbBuffer[wCount] == 0) 114 { 115 wCount--; 116 } 117 } 118 #endif 119 } 120 121 /************************************************************************ 122 FUNCTION: syncmldm_sec_build_basic_cred 123 124 DESCRIPTION: This function build the credentials for basic 125 authentication scheme: 126 Let B64 = the base64 encoding function. 127 Credential String = B64(username:password) 128 129 ARGUMENTS PASSED: 130 131 SYNCMLDM_BASIC_SEC_INFO_T *ps_basic_sec_info 132 - Reference to the structure containg user name and password. 133 134 RETURN VALUE: 135 SYNCMLDM_SEC_CREDENTIALS_T* 136 - Reference to the structure containing credential string and 137 its length. 138 139 PRE-CONDITIONS: 140 141 142 POST-CONDITIONS: 143 Caller MUST free the memory allocated by the callee for the 144 return structure and data members of the structure. 145 146 IMPORTANT NOTES: 147 None 148 ************************************************************************/ 149 SYNCMLDM_SEC_CREDENTIALS_T* syncmldm_sec_build_basic_cred( 150 const SYNCMLDM_BASIC_SEC_INFO_T *ps_basic_sec_info) 151 { 152 UINT8 *pb_username_and_password = NULL; 153 UINT8 ab_savebytes[MAXIMUM_SAVE_BYTES]; 154 UINT32 dw_client_cred_length = 0; 155 UINT32 dw_offset = 0; 156 UINT32 dw_length = 0; 157 UINT32 dw_estimated_basic_cred_length = 0; 158 SYNCMLDM_SEC_CREDENTIALS_T *ps_security_credential = NULL; 159 160 memset(ab_savebytes, '\0', MAXIMUM_SAVE_BYTES); 161 162 /* To build basic credential string both user name and password 163 * are mandatory if either use name or password is null then 164 * this function return NULL. 165 */ 166 if((ps_basic_sec_info == NULL) || 167 (ps_basic_sec_info->pb_user_name_or_server_id == NULL) || 168 (ps_basic_sec_info->pb_password == NULL)) 169 { 170 return (SYNCMLDM_SEC_CREDENTIALS_T*)NULL; 171 } 172 173 /* We have to add COLON_PLUS_NULL because we have to add ':' 174 * length and null character length 175 */ 176 dw_length = 177 ((DmStrlen((CPCHAR)ps_basic_sec_info->pb_user_name_or_server_id) 178 + DmStrlen((CPCHAR)ps_basic_sec_info->pb_password)) 179 + COLON_PLUS_NULL); 180 181 /* RFC 2045 say's (in First paragraph of Section 6.8) 182 * "The encoding and decoding algorithms are simple, but the 183 * encoded data are consistently only about 33% larger than the 184 * unencoded data.". That's why i am calculating 185 * dw_estimated_basic_cred_length by dw_length + (dw_length/2) 186 */ 187 dw_estimated_basic_cred_length = dw_length + (dw_length/2); 188 189 ps_security_credential = (SYNCMLDM_SEC_CREDENTIALS_T*) 190 DmAllocMem((sizeof(UINT16) + (sizeof(UINT8) * dw_estimated_basic_cred_length))); 191 if(ps_security_credential == NULL) 192 { 193 return ps_security_credential; 194 } 195 196 ps_security_credential->w_credential_string_length = 0; 197 198 pb_username_and_password = (UINT8*)DmAllocMem(dw_length); 199 if(pb_username_and_password == NULL) 200 { 201 DmFreeMem(ps_security_credential); 202 return (SYNCMLDM_SEC_CREDENTIALS_T*)NULL; 203 } 204 205 memset(ps_security_credential->ab_credential_string, '\0', dw_estimated_basic_cred_length); 206 memset(pb_username_and_password, '\0',dw_length); 207 208 dw_client_cred_length = 209 DmStrlen((CPCHAR)ps_basic_sec_info->pb_user_name_or_server_id); 210 211 memcpy(pb_username_and_password, 212 ps_basic_sec_info->pb_user_name_or_server_id, 213 dw_client_cred_length); 214 215 /* We have to add the ':' after UserName to build the 216 * basic credential string 217 */ 218 pb_username_and_password[dw_client_cred_length++] = ':'; 219 220 memcpy(&pb_username_and_password[dw_client_cred_length], 221 ps_basic_sec_info->pb_password, 222 DmStrlen((CPCHAR)ps_basic_sec_info->pb_password)); 223 224 dw_client_cred_length += DmStrlen((CPCHAR)ps_basic_sec_info->pb_password); 225 226 /* base64Encode function encodes the (UserName:Password) to 227 * base64 encoding and it return the lenght of the encoded 228 * string 229 */ 230 ps_security_credential->w_credential_string_length = 231 (UINT16)base64Encode( 232 ps_security_credential->ab_credential_string, 233 dw_estimated_basic_cred_length, 234 pb_username_and_password, 235 (unsigned long*)&dw_client_cred_length, 236 (unsigned long*)&dw_offset, SYNCML_DM_NEXT_BLOCK, 237 ab_savebytes 238 ); 239 240 DmFreeMem(pb_username_and_password); 241 242 return ps_security_credential; 243 } 244 245 /************************************************************************ 246 FUNCTION: build_md5_cred 247 248 DESCRIPTION: This function build the credentials for MD5 249 authentication scheme: 250 Let H = the MD5 Hashing function. 251 Let Digest = the output of the MD5 Hashing function. 252 Let B64 = the base64 encoding function. 253 Credential String = H(B64(H(username:password)):nonce) 254 255 ARGUMENTS PASSED: 256 257 SYNCMLDM_MD5_SEC_INFO_T *ps_md5_sec_info 258 - Reference to the structure containing user name, password 259 and nonce. 260 261 RETURN VALUE: 262 SYNCMLDM_SEC_CREDENTIALS_T* 263 - Reference to the structure containing credential string and 264 it's length. 265 266 PRE-CONDITIONS: 267 268 POST-CONDITIONS: 269 Caller MUST free the memory allocated by the callee for the 270 return parameter. 271 272 IMPORTANT NOTES: 273 None 274 ************************************************************************/ 275 SYNCMLDM_SEC_CREDENTIALS_T* syncmldm_sec_build_md5_cred( 276 const SYNCMLDM_MD5_SEC_INFO_T *ps_md5_sec_info) 277 { 278 UINT8 ab_savebytes[MAXIMUM_SAVE_BYTES]; 279 280 UINT32 dw_client_cred_length = 0; 281 UINT32 dw_offset = 0; 282 283 MD5_CTX s_md5_ctx; 284 UINT8 ab_hash[SYNCML_DM_HASHLEN]; /* Contains the hash data after 285 * smlMD5Final function is called 286 */ 287 288 SYNCMLDM_SEC_CREDENTIALS_T *ps_security_credential = NULL; 289 290 memset(ab_hash, '\0', SYNCML_DM_HASHLEN); 291 memset(ab_savebytes, '\0', MAXIMUM_SAVE_BYTES); 292 293 if((ps_md5_sec_info == NULL) || 294 (ps_md5_sec_info->pb_user_name_or_server_id == NULL) || 295 (ps_md5_sec_info->pb_password == NULL) || 296 (ps_md5_sec_info->pb_nonce == NULL)) 297 { 298 return ps_security_credential; 299 } 300 301 ps_security_credential = (SYNCMLDM_SEC_CREDENTIALS_T*) 302 DmAllocMem((sizeof(UINT16) + (sizeof(UINT8) + SYNCML_DM_BAS64_ENCODING_SIZE_IN_MD5))); 303 if(ps_security_credential == NULL) 304 { 305 return ps_security_credential; 306 } 307 308 memset(ps_security_credential->ab_credential_string, '\0', SYNCML_DM_BAS64_ENCODING_SIZE_IN_MD5); 309 310 /****** Calculation of the part B64(H(username:password) **********/ 311 smlMD5Init(&s_md5_ctx); 312 smlMD5Update(&s_md5_ctx, ps_md5_sec_info->pb_user_name_or_server_id, 313 DmStrlen((CPCHAR)ps_md5_sec_info->pb_user_name_or_server_id)); 314 smlMD5Update(&s_md5_ctx, (UINT8*)":", 1); 315 smlMD5Update(&s_md5_ctx, ps_md5_sec_info->pb_password, 316 DmStrlen((CPCHAR)ps_md5_sec_info->pb_password)); 317 smlMD5Final(ab_hash, &s_md5_ctx); 318 dw_client_cred_length = SYNCML_DM_HASHLEN; 319 dw_client_cred_length = base64Encode( 320 ps_security_credential->ab_credential_string, 321 SYNCML_DM_BAS64_ENCODING_SIZE_IN_MD5, 322 ab_hash, 323 (unsigned long*)&dw_client_cred_length, 324 (unsigned long*)&dw_offset, SYNCML_DM_NEXT_BLOCK, 325 ab_savebytes); 326 /**** End of the Calculation of part B64(H(username:password) *****/ 327 328 /*** Calculation of the part H(B64(H(username:password)):nonce) ***/ 329 smlMD5Init(&s_md5_ctx); 330 smlMD5Update(&s_md5_ctx, ps_security_credential->ab_credential_string, dw_client_cred_length); 331 smlMD5Update(&s_md5_ctx, (UINT8*)":", 1); 332 smlMD5Update(&s_md5_ctx, ps_md5_sec_info->pb_nonce, ps_md5_sec_info->w_nonce_length); 333 smlMD5Final(ab_hash, &s_md5_ctx); 334 dw_client_cred_length = SYNCML_DM_HASHLEN; 335 336 if(ps_md5_sec_info->o_encode_base64 == TRUE) 337 { 338 ps_security_credential->w_credential_string_length = 339 (UINT16)base64Encode(ps_security_credential->ab_credential_string, 340 SYNCML_DM_BAS64_ENCODING_SIZE_IN_MD5, 341 ab_hash, 342 (unsigned long*)&dw_client_cred_length, 343 (unsigned long*)&dw_offset, SYNCML_DM_NEXT_BLOCK, 344 ab_savebytes 345 ); 346 } 347 else 348 { 349 ps_security_credential->w_credential_string_length = 350 (UINT16)dw_client_cred_length; 351 memcpy(ps_security_credential->ab_credential_string, 352 &ab_hash, 353 dw_client_cred_length); 354 } 355 /****** End of the Calculation of part 356 H(B64(H(username:password)):nonce) *****/ 357 return ps_security_credential; 358 } 359 360 /************************************************************************ 361 FUNCTION: build_hmac_cred 362 363 DESCRIPTION: This function build the credentials for HMAC 364 authentication scheme: 365 Let H = the MD5 Hashing function. 366 Let Digest = the output of the MD5 Hashing function. 367 Let B64 = the base64 encoding function. 368 Credential String = 369 H(B64(H(username:password)):nonce:B64(H(message body))) 370 371 ARGUMENTS PASSED: 372 SYNCMLDM_HMAC_SEC_INFO_T *ps_hmac_sec_info 373 - Reference to the structure containing user name, password, 374 nonce and starting pointer to the SyncML Document. 375 376 RETURN VALUE: 377 SYNCMLDM_SEC_CREDENTIALS_T* 378 - Reference to the structure containing credential string and 379 it's length. 380 381 PRE-CONDITIONS: 382 383 POST-CONDITIONS: 384 Caller MUST free the memory allocated by the callee for the 385 return parameter. 386 387 IMPORTANT NOTES: 388 None 389 ************************************************************************/ 390 SYNCMLDM_SEC_CREDENTIALS_T* syncmldm_sec_build_hmac_cred( 391 const SYNCMLDM_HMAC_SEC_INFO_T *ps_hmac_sec_info) 392 { 393 UINT8 ab_savebytes[MAXIMUM_SAVE_BYTES]; 394 395 UINT32 dw_client_cred_length = 0; 396 UINT32 dw_body_encoded_length = 0; 397 UINT32 dw_hash_length = SYNCML_DM_HASHLEN; 398 UINT32 dw_offset = 0; 399 400 MD5_CTX s_md5_ctx; 401 UINT8 ab_hash[SYNCML_DM_HASHLEN]; 402 403 SYNCMLDM_SEC_CREDENTIALS_T *ps_security_credential = NULL; 404 405 memset(ab_savebytes, '\0', MAXIMUM_SAVE_BYTES); 406 memset(ab_hash, '\0', SYNCML_DM_HASHLEN); 407 408 /* If any one of the following parameter is NULL hash can't 409 * be build. 410 */ 411 if((ps_hmac_sec_info == NULL) || 412 (ps_hmac_sec_info->pb_user_name_or_server_id == NULL) || 413 (ps_hmac_sec_info->pb_password == NULL) || 414 (ps_hmac_sec_info->pb_nonce == NULL) || 415 (ps_hmac_sec_info->pb_syncml_document == NULL) || 416 (ps_hmac_sec_info->dw_syncml_document_length == 0)) 417 { 418 return ps_security_credential; 419 } 420 421 ps_security_credential = (SYNCMLDM_SEC_CREDENTIALS_T*) DmAllocMem((sizeof(UINT8) + (sizeof(UINT8) + 422 SYNCML_DM_MAX_CRED_BUFFER_SIZE))); 423 if(ps_security_credential == NULL) 424 { 425 return ps_security_credential; 426 } 427 428 memset(ps_security_credential->ab_credential_string, '\0', SYNCML_DM_MAX_CRED_BUFFER_SIZE); 429 430 /***** Calculation of the part B64(H(username:password) ******/ 431 smlMD5Init(&s_md5_ctx); 432 smlMD5Update(&s_md5_ctx, 433 ps_hmac_sec_info->pb_user_name_or_server_id, 434 DmStrlen((CPCHAR)ps_hmac_sec_info->pb_user_name_or_server_id)); 435 436 smlMD5Update(&s_md5_ctx, (UINT8*)":", 1); 437 smlMD5Update(&s_md5_ctx, ps_hmac_sec_info->pb_password, 438 DmStrlen((CPCHAR)ps_hmac_sec_info->pb_password)); 439 smlMD5Final(ab_hash, &s_md5_ctx); 440 dw_client_cred_length = SYNCML_DM_HASHLEN; 441 dw_client_cred_length = 442 base64Encode(ps_security_credential->ab_credential_string, 443 SYNCML_DM_MAX_CRED_BUFFER_SIZE, 444 ab_hash, 445 (unsigned long*)&dw_client_cred_length, 446 (unsigned long*)&dw_offset, SYNCML_DM_NEXT_BLOCK, 447 ab_savebytes); 448 /*** End of the Calculation of part B64(H(username:password) ****/ 449 450 ps_security_credential->ab_credential_string[dw_client_cred_length++] = ':'; 451 memcpy(&(ps_security_credential->ab_credential_string[dw_client_cred_length]), 452 ps_hmac_sec_info->pb_nonce, 453 ps_hmac_sec_info->w_nonce_length); 454 455 dw_client_cred_length = dw_client_cred_length + 456 ps_hmac_sec_info->w_nonce_length; 457 ps_security_credential->ab_credential_string[dw_client_cred_length++] 458 = ':'; 459 460 /********** Calculation of B64(H(message body)) *****************/ 461 smlMD5Init(&s_md5_ctx); 462 smlMD5Update(&s_md5_ctx, ps_hmac_sec_info->pb_syncml_document, 463 ps_hmac_sec_info->dw_syncml_document_length); 464 smlMD5Final(ab_hash, &s_md5_ctx); 465 dw_body_encoded_length = base64Encode(&ps_security_credential->ab_credential_string[dw_client_cred_length], 466 SYNCML_DM_MAX_CRED_BUFFER_SIZE, 467 ab_hash, 468 (unsigned long*)&dw_hash_length, 469 (unsigned long*)&dw_offset, SYNCML_DM_NEXT_BLOCK, 470 ab_savebytes); 471 /******** End of the Calculation of B64(H(message body)) *******/ 472 473 dw_client_cred_length += dw_body_encoded_length; 474 475 /****** Calculation of 476 H(B64(H(username:password)):nonce:B64(H(message body))) *****/ 477 smlMD5Init(&s_md5_ctx); 478 smlMD5Update(&s_md5_ctx, 479 ps_security_credential->ab_credential_string, 480 dw_client_cred_length); 481 smlMD5Final(ab_hash, &s_md5_ctx); 482 483 /* Reset the length variable.*/ 484 dw_hash_length = SYNCML_DM_HASHLEN; 485 486 if(ps_hmac_sec_info->o_encode_base64 == TRUE) 487 { 488 dw_client_cred_length = SYNCML_DM_HASHLEN; 489 ps_security_credential->w_credential_string_length = 490 (UINT16)base64Encode( 491 ps_security_credential->ab_credential_string, 492 SYNCML_DM_MAX_CRED_BUFFER_SIZE, 493 ab_hash, 494 (unsigned long*)&dw_client_cred_length, 495 (unsigned long*)&dw_offset, SYNCML_DM_NEXT_BLOCK, 496 ab_savebytes 497 ); 498 } 499 else 500 { 501 ps_security_credential->w_credential_string_length = 502 (UINT16)dw_hash_length; 503 memcpy(ps_security_credential->ab_credential_string, &ab_hash, 504 dw_hash_length); 505 } 506 ps_security_credential->ab_credential_string 507 [ps_security_credential->w_credential_string_length] = '\0'; 508 /****** End of the calculation of 509 H(B64(H(username:password)):nonce:B64(H(message body))) *****/ 510 return ps_security_credential; 511 } 512 513 /************************************************************************ 514 FUNCTION: syncmldm_sec_generate_nonce 515 516 DESCRIPTION: This function generate the nonce.: 517 Let H = the MD5 Hashing function. 518 Let B64 = the base64 encoding function. 519 Nonce String = 520 b64(H(Random number+IMEI+User Name+Password+ServerId)) 521 522 ARGUMENTS PASSED: 523 SYNCMLDM_NONCE_GENERATE_PARAMETER_INFO_T *ps_nonce_gen_parameters 524 - Reference to the structure containing user name, password, 525 serverid. 526 527 RETURN VALUE: 528 SYNCMLDM_NONCE_STRING_INFO_T* 529 - Reference to the structure containing nonce string and 530 it's length. 531 532 PRE-CONDITIONS: 533 534 POST-CONDITIONS: 535 Caller MUST free the memory allocated by the callee for the 536 return parameter. 537 538 IMPORTANT NOTES: 539 None 540 ************************************************************************/ 541 SYNCMLDM_NONCE_STRING_INFO_T* syncmldm_sec_generate_nonce( 542 const SYNCMLDM_NONCE_GENERATE_PARAMETER_INFO_T *ps_nonce_gen_parameters, 543 CPCHAR devID) 544 { 545 UINT8 ab_hash[SYNCML_DM_HASHLEN]; 546 UINT8 ab_savebytes[MAXIMUM_SAVE_BYTES]; 547 UINT8 *pb_nonce_string_parameters = NULL; 548 UINT8 ab_pseudo_random[SYNCML_DM_PSEUDO_RANDOM_NUM_LENGTH]; 549 550 UINT32 dw_current_string_length = 0; 551 UINT32 dw_total_length = 0; 552 UINT32 dw_hash_length = SYNCML_DM_HASHLEN; 553 UINT32 dw_offset = 0; 554 UINT32 lengthDevID; 555 556 MD5_CTX s_md5_ctx; 557 558 SYNCMLDM_NONCE_STRING_INFO_T *ps_nonce_string_info = NULL; 559 560 561 if(ps_nonce_gen_parameters == NULL || !devID) 562 { 563 return NULL; 564 } 565 566 lengthDevID = DmStrlen(devID); 567 memset(ab_hash, '\0', SYNCML_DM_HASHLEN); 568 memset(ab_savebytes, '\0', MAXIMUM_SAVE_BYTES); 569 570 get_pseudo_random(ab_pseudo_random, SYNCML_DM_PSEUDO_RANDOM_NUM_LENGTH); 571 572 dw_total_length = 573 DmStrlen((CPCHAR)ps_nonce_gen_parameters->pb_user_name) + 574 DmStrlen((CPCHAR)ps_nonce_gen_parameters->pb_password) + 575 DmStrlen((CPCHAR)ps_nonce_gen_parameters->pb_server_id) + 576 SYNCML_DM_PSEUDO_RANDOM_NUM_LENGTH + lengthDevID + 1; 577 pb_nonce_string_parameters = (UINT8*)DmAllocMem((sizeof(char) * dw_total_length)); 578 if(pb_nonce_string_parameters == NULL) 579 { 580 return NULL; 581 } 582 583 ps_nonce_string_info = (SYNCMLDM_NONCE_STRING_INFO_T*) 584 DmAllocMem((sizeof(UINT16) + (sizeof(UINT8) * SYNCML_DM_MAX_CRED_BUFFER_SIZE))); 585 if(ps_nonce_string_info == NULL) 586 { 587 DmFreeMem(pb_nonce_string_parameters); 588 return ps_nonce_string_info; 589 } 590 591 memset(pb_nonce_string_parameters, '\0', dw_total_length); 592 memset(ps_nonce_string_info->ab_nonce_string,'\0', SYNCML_DM_MAX_CRED_BUFFER_SIZE); 593 594 dw_total_length = 0; 595 596 /* Adding RandomNumber, IMEI, UserName, Password and ServerId 597 */ 598 dw_current_string_length = SYNCML_DM_PSEUDO_RANDOM_NUM_LENGTH; 599 memcpy(pb_nonce_string_parameters, 600 ab_pseudo_random, 601 dw_current_string_length); 602 dw_total_length += dw_current_string_length; 603 604 dw_current_string_length = lengthDevID; 605 memcpy(&pb_nonce_string_parameters[dw_total_length],devID,dw_current_string_length); 606 dw_total_length += dw_current_string_length; 607 608 dw_current_string_length = DmStrlen((CPCHAR)ps_nonce_gen_parameters->pb_user_name); 609 memcpy(&pb_nonce_string_parameters[dw_total_length], 610 ps_nonce_gen_parameters->pb_user_name, 611 dw_current_string_length); 612 dw_total_length += dw_current_string_length; 613 614 dw_current_string_length = DmStrlen((CPCHAR)ps_nonce_gen_parameters->pb_password); 615 memcpy(&pb_nonce_string_parameters[dw_total_length], 616 ps_nonce_gen_parameters->pb_password, 617 dw_current_string_length); 618 dw_total_length += dw_current_string_length; 619 620 dw_current_string_length = DmStrlen((CPCHAR)ps_nonce_gen_parameters->pb_server_id); 621 memcpy(&pb_nonce_string_parameters[dw_total_length], 622 ps_nonce_gen_parameters->pb_server_id, 623 dw_current_string_length); 624 dw_total_length += dw_current_string_length; 625 626 /* Hashing the nonce string */ 627 smlMD5Init(&s_md5_ctx); 628 smlMD5Update(&s_md5_ctx, pb_nonce_string_parameters, dw_total_length); 629 smlMD5Final(ab_hash, &s_md5_ctx); 630 631 /* Encoding the generated nonce string into base64 */ 632 ps_nonce_string_info->w_nonce_string_length = 633 (UINT16)base64Encode( 634 ps_nonce_string_info->ab_nonce_string, 635 SYNCML_DM_MAX_CRED_BUFFER_SIZE, 636 ab_hash, 637 (unsigned long*)&dw_hash_length, 638 (unsigned long*)&dw_offset, SYNCML_DM_NEXT_BLOCK, 639 ab_savebytes 640 ); 641 642 DmFreeMem(pb_nonce_string_parameters); 643 644 ps_nonce_string_info->ab_nonce_string[ps_nonce_string_info->w_nonce_string_length] = '\0'; 645 return ps_nonce_string_info; 646 } 647 648 /************************************************************************ 649 FUNCTION: build_digest_cred 650 651 DESCRIPTION: This function build the credentials for MD5 652 authentication scheme: 653 Let H = the MD5 Hashing function. 654 Let Digest = the output of the MD5 Hashing function. 655 Let B64 = the base64 encoding function. 656 Credential String = H(B64(H(username:password)):nonce) 657 658 ARGUMENTS PASSED: 659 660 SYNCMLDM_MD5_SEC_INFO_T *ps_md5_sec_info 661 - Reference to the structure containing user name, password 662 and nonce. 663 664 RETURN VALUE: 665 SYNCMLDM_SEC_CREDENTIALS_T* 666 - Reference to the structure containing credential string and 667 it's length. 668 669 PRE-CONDITIONS: 670 671 POST-CONDITIONS: 672 Caller MUST free the memory allocated by the callee for the 673 return parameter. 674 675 IMPORTANT NOTES: 676 None 677 ************************************************************************/ 678 SYNCMLDM_SEC_CREDENTIALS_T* syncmldm_sec_build_digest_cred( 679 const SYNCMLDM_MD5_SEC_INFO_T *ps_md5_sec_info) 680 { 681 UINT8 ab_savebytes[MAXIMUM_SAVE_BYTES]; 682 683 UINT32 dw_client_cred_length = 0; 684 UINT32 dw_offset = 0; 685 686 MD5_CTX s_md5_ctx; 687 UINT8 ab_hash[SYNCML_DM_HASHLEN]; /* Contains the hash data after 688 * smlMD5Final function is called 689 */ 690 691 SYNCMLDM_SEC_CREDENTIALS_T *ps_security_credential = NULL; 692 693 memset(ab_hash, '\0', SYNCML_DM_HASHLEN); 694 memset(ab_savebytes, '\0', MAXIMUM_SAVE_BYTES); 695 696 if ((ps_md5_sec_info == NULL) || 697 (ps_md5_sec_info->pb_user_name_or_server_id == NULL) || 698 (ps_md5_sec_info->pb_password == NULL) ) 699 { 700 return ps_security_credential; 701 } 702 703 ps_security_credential = (SYNCMLDM_SEC_CREDENTIALS_T*) 704 DmAllocMem((sizeof(UINT16) + (sizeof(UINT8) + SYNCML_DM_HASHLEN))); 705 if(ps_security_credential == NULL) 706 { 707 return ps_security_credential; 708 } 709 710 memset(ps_security_credential->ab_credential_string, '0', SYNCML_DM_HASHLEN); 711 712 713 smlMD5Init(&s_md5_ctx); 714 smlMD5Update(&s_md5_ctx, ps_md5_sec_info->pb_user_name_or_server_id, 715 DmStrlen((CPCHAR)ps_md5_sec_info->pb_user_name_or_server_id)); 716 UINT8 *p_nonce = NULL; 717 if ( NULL != ps_md5_sec_info->pb_nonce ) 718 { 719 int nonceLen = DmStrlen((CPCHAR)ps_md5_sec_info->pb_nonce); 720 p_nonce = DmAllocMem(nonceLen + 2); 721 if(p_nonce == NULL) 722 { 723 DmFreeMem(ps_security_credential); 724 return (SYNCMLDM_SEC_CREDENTIALS_T*)NULL; 725 } 726 memcpy(p_nonce + 1, ps_md5_sec_info->pb_nonce, nonceLen); 727 p_nonce[0]= ':'; 728 p_nonce[nonceLen]= ':'; 729 smlMD5Update(&s_md5_ctx, (UINT8*)p_nonce, nonceLen + 2); 730 } 731 else 732 { 733 smlMD5Update(&s_md5_ctx, (UINT8*)":", 1); 734 } 735 smlMD5Update(&s_md5_ctx, ps_md5_sec_info->pb_password, 736 DmStrlen((CPCHAR)ps_md5_sec_info->pb_password)); 737 smlMD5Final(ab_hash, &s_md5_ctx); 738 739 memcpy(ps_security_credential->ab_credential_string, 740 &ab_hash, 741 SYNCML_DM_HASHLEN); 742 743 if ( NULL != p_nonce ) 744 { 745 DmFreeMem(p_nonce); 746 p_nonce = NULL; 747 } 748 749 return ps_security_credential; 750 } 751 752 #ifdef __cplusplus 753 } 754 #endif 755