Home | History | Annotate | Download | only in src
      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