/* * Entropy accumulator update */ static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, const unsigned char *data, size_t len ) { unsigned char header[2]; unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; size_t use_len = len; const unsigned char *p = data; if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) { #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512( data, len, tmp, 0 ); #else mbedtls_sha256( data, len, tmp, 0 ); #endif p = tmp; use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; } header[0] = source_id; header[1] = use_len & 0xFF; #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512_update( &ctx->accumulator, header, 2 ); mbedtls_sha512_update( &ctx->accumulator, p, use_len ); #else mbedtls_sha256_update( &ctx->accumulator, header, 2 ); mbedtls_sha256_update( &ctx->accumulator, p, use_len ); #endif return( 0 ); }
int crypto_hash_sha256(unsigned char *out, const unsigned char *in, unsigned long long inlen) { mbedtls_sha256(in, inlen, out, 0); return 0; }
static void Curl_mbedtls_sha256sum(const unsigned char *input, size_t inputlen, unsigned char *sha256sum, size_t sha256len UNUSED_PARAM) { (void)sha256len; mbedtls_sha256(input, inputlen, sha256sum, 0); }
JsVar *jswrap_crypto_SHAx(JsVar *message, int shaNum) { JSV_GET_AS_CHAR_ARRAY(msgPtr, msgLen, message); if (!msgPtr) return 0; int bufferSize = 20; if (shaNum>1) bufferSize = shaNum/8; char *outPtr = 0; JsVar *outArr = jsvNewArrayBufferWithPtr((unsigned int)bufferSize, &outPtr); if (!outPtr) { jsError("Not enough memory for result"); return 0; } if (shaNum==1) mbedtls_sha1((unsigned char *)msgPtr, msgLen, (unsigned char *)outPtr); else if (shaNum==224) mbedtls_sha256((unsigned char *)msgPtr, msgLen, (unsigned char *)outPtr, true/*224*/); else if (shaNum==256) mbedtls_sha256((unsigned char *)msgPtr, msgLen, (unsigned char *)outPtr, false/*256*/); else if (shaNum==384) mbedtls_sha512((unsigned char *)msgPtr, msgLen, (unsigned char *)outPtr, true/*384*/); else if (shaNum==512) mbedtls_sha512((unsigned char *)msgPtr, msgLen, (unsigned char *)outPtr, false/*512*/); return outArr; }
static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input, size_t inputlen, unsigned char *sha256sum, size_t sha256len UNUSED_PARAM) { (void)sha256len; #if MBEDTLS_VERSION_NUMBER < 0x02070000 mbedtls_sha256(input, inputlen, sha256sum, 0); #else /* returns 0 on success, otherwise failure */ if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0) return CURLE_BAD_FUNCTION_ARGUMENT; #endif return CURLE_OK; }
static int gen_auth_key(mbedtls_ecdh_context *key, const char *tempKey, const char *salt, unsigned char *buf, size_t bufLen) { int ret = 0; size_t olen = 0; if ((errno = dslink_base64_url_decode(buf, bufLen, &olen, (unsigned char *) tempKey, strlen(tempKey))) != 0) { ret = DSLINK_CRYPT_BASE64_URL_DECODE_ERR; goto exit; } if ((errno = mbedtls_ecp_point_read_binary(&key->grp, &key->Qp, buf, olen)) != 0) { ret = DSLINK_HANDSHAKE_INVALID_TMP_KEY; goto exit; } if ((errno = mbedtls_ecdh_calc_secret(key, &olen, buf, bufLen, NULL, NULL)) != 0) { ret = DSLINK_HANDSHAKE_INVALID_TMP_KEY; goto exit; } { size_t saltLen = strlen(salt); size_t len = saltLen + olen; char *in = malloc(len + 1); if (!in) { ret = DSLINK_ALLOC_ERR; goto exit; } memcpy(in, salt, saltLen); memcpy(in + saltLen, (char *) buf, olen); *(in + len) = '\0'; unsigned char auth[32]; mbedtls_sha256((unsigned char *) in, len, auth, 0); free(in); if ((errno = dslink_base64_url_encode(buf, bufLen, &olen, auth, sizeof(auth))) != 0) { ret = DSLINK_CRYPT_BASE64_URL_ENCODE_ERR; } } exit: return ret; }
static void sha256_wrap( const unsigned char *input, size_t ilen, unsigned char *output ) { mbedtls_sha256( input, ilen, output, 0 ); }
int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) { int ret, count = 0, i, done; mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); #if defined(MBEDTLS_THREADING_C) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) return( ret ); #endif /* * Always gather extra entropy before a call */ do { if( count++ > ENTROPY_MAX_LOOP ) { ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; goto exit; } if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) goto exit; done = 1; for( i = 0; i < ctx->source_count; i++ ) if( ctx->source[i].size < ctx->source[i].threshold ) done = 0; } while( ! done ); memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512_finish( &ctx->accumulator, buf ); /* * Reset accumulator and counters and recycle existing entropy */ memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) ); mbedtls_sha512_starts( &ctx->accumulator, 0 ); mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); /* * Perform second SHA-512 on entropy */ mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ mbedtls_sha256_finish( &ctx->accumulator, buf ); /* * Reset accumulator and counters and recycle existing entropy */ memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) ); mbedtls_sha256_starts( &ctx->accumulator, 0 ); mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); /* * Perform second SHA-256 on entropy */ mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ for( i = 0; i < ctx->source_count; i++ ) ctx->source[i].size = 0; memcpy( output, buf, len ); ret = 0; exit: #if defined(MBEDTLS_THREADING_C) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); #endif return( ret ); }
pthread_addr_t tls_benchmark_cb(void *args) { int i; int argc; char **argv; unsigned char tmp[200]; char title[TITLE_LEN]; todo_list todo; #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) unsigned char alloc_buf[HEAP_SIZE] = { 0 }; #endif argc = ((struct pthread_arg *)args)->argc; argv = ((struct pthread_arg *)args)->argv; if (argc <= 1) { memset(&todo, 1, sizeof(todo)); } else { memset(&todo, 0, sizeof(todo)); for (i = 1; i < argc; i++) { if (strcmp(argv[i], "md4") == 0) { todo.md4 = 1; } else if (strcmp(argv[i], "md5") == 0) { todo.md5 = 1; } else if (strcmp(argv[i], "ripemd160") == 0) { todo.ripemd160 = 1; } else if (strcmp(argv[i], "sha1") == 0) { todo.sha1 = 1; } else if (strcmp(argv[i], "sha256") == 0) { todo.sha256 = 1; } else if (strcmp(argv[i], "sha512") == 0) { todo.sha512 = 1; } else if (strcmp(argv[i], "arc4") == 0) { todo.arc4 = 1; } else if (strcmp(argv[i], "des3") == 0) { todo.des3 = 1; } else if (strcmp(argv[i], "des") == 0) { todo.des = 1; } else if (strcmp(argv[i], "aes_cbc") == 0) { todo.aes_cbc = 1; } else if (strcmp(argv[i], "aes_gcm") == 0) { todo.aes_gcm = 1; } else if (strcmp(argv[i], "aes_ccm") == 0) { todo.aes_ccm = 1; } else if (strcmp(argv[i], "aes_cmac") == 0) { todo.aes_cmac = 1; } else if (strcmp(argv[i], "des3_cmac") == 0) { todo.des3_cmac = 1; } else if (strcmp(argv[i], "camellia") == 0) { todo.camellia = 1; } else if (strcmp(argv[i], "blowfish") == 0) { todo.blowfish = 1; } else if (strcmp(argv[i], "havege") == 0) { todo.havege = 1; } else if (strcmp(argv[i], "ctr_drbg") == 0) { todo.ctr_drbg = 1; } else if (strcmp(argv[i], "hmac_drbg") == 0) { todo.hmac_drbg = 1; } else if (strcmp(argv[i], "rsa") == 0) { todo.rsa = 1; } else if (strcmp(argv[i], "dhm") == 0) { todo.dhm = 1; } else if (strcmp(argv[i], "ecdsa") == 0) { todo.ecdsa = 1; } else if (strcmp(argv[i], "ecdh") == 0) { todo.ecdh = 1; } else { mbedtls_printf("Unrecognized option: %s\n", argv[i]); mbedtls_printf("Available options: " OPTIONS); } } } mbedtls_printf("\n"); #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init(alloc_buf, sizeof(alloc_buf)); #endif memset(buf, 0xAA, sizeof(buf)); memset(tmp, 0xBB, sizeof(tmp)); #if defined(MBEDTLS_MD4_C) if (todo.md4) { TIME_AND_TSC("MD4", mbedtls_md4(buf, BUFSIZE, tmp)); } #endif #if defined(MBEDTLS_MD5_C) if (todo.md5) { TIME_AND_TSC("MD5", mbedtls_md5(buf, BUFSIZE, tmp)); } #endif #if defined(MBEDTLS_RIPEMD160_C) if (todo.ripemd160) { TIME_AND_TSC("RIPEMD160", mbedtls_ripemd160(buf, BUFSIZE, tmp)); } #endif #if defined(MBEDTLS_SHA1_C) if (todo.sha1) { TIME_AND_TSC("SHA-1", mbedtls_sha1(buf, BUFSIZE, tmp)); } #endif #if defined(MBEDTLS_SHA256_C) if (todo.sha256) { TIME_AND_TSC("SHA-256", mbedtls_sha256(buf, BUFSIZE, tmp, 0)); } #endif #if defined(MBEDTLS_SHA512_C) if (todo.sha512) { TIME_AND_TSC("SHA-512", mbedtls_sha512(buf, BUFSIZE, tmp, 0)); } #endif #if defined(MBEDTLS_ARC4_C) if (todo.arc4) { mbedtls_arc4_context arc4; mbedtls_arc4_init(&arc4); mbedtls_arc4_setup(&arc4, tmp, 32); TIME_AND_TSC("ARC4", mbedtls_arc4_crypt(&arc4, BUFSIZE, buf, buf)); mbedtls_arc4_free(&arc4); } #endif #if defined(MBEDTLS_DES_C) #if defined(MBEDTLS_CIPHER_MODE_CBC) if (todo.des3) { mbedtls_des3_context des3; mbedtls_des3_init(&des3); mbedtls_des3_set3key_enc(&des3, tmp); TIME_AND_TSC("3DES", mbedtls_des3_crypt_cbc(&des3, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf)); mbedtls_des3_free(&des3); } if (todo.des) { mbedtls_des_context des; mbedtls_des_init(&des); mbedtls_des_setkey_enc(&des, tmp); TIME_AND_TSC("DES", mbedtls_des_crypt_cbc(&des, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf)); mbedtls_des_free(&des); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CMAC_C) if (todo.des3_cmac) { unsigned char output[8]; const mbedtls_cipher_info_t *cipher_info; memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_EDE3_ECB); TIME_AND_TSC("3DES-CMAC", mbedtls_cipher_cmac(cipher_info, tmp, 192, buf, BUFSIZE, output)); } #endif /* MBEDTLS_CMAC_C */ #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) #if defined(MBEDTLS_CIPHER_MODE_CBC) if (todo.aes_cbc) { int keysize; mbedtls_aes_context aes; mbedtls_aes_init(&aes); for (keysize = 128; keysize <= 256; keysize += 64) { mbedtls_snprintf(title, sizeof(title), "AES-CBC-%d", keysize); memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); mbedtls_aes_setkey_enc(&aes, tmp, keysize); TIME_AND_TSC(title, mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, BUFSIZE, tmp, buf, buf)); } mbedtls_aes_free(&aes); } #endif #if defined(MBEDTLS_GCM_C) if (todo.aes_gcm) { int keysize; mbedtls_gcm_context gcm; mbedtls_gcm_init(&gcm); for (keysize = 128; keysize <= 256; keysize += 64) { mbedtls_snprintf(title, sizeof(title), "AES-GCM-%d", keysize); memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, tmp, keysize); TIME_AND_TSC(title, mbedtls_gcm_crypt_and_tag(&gcm, MBEDTLS_GCM_ENCRYPT, BUFSIZE, tmp, 12, NULL, 0, buf, buf, 16, tmp)); mbedtls_gcm_free(&gcm); } } #endif #if defined(MBEDTLS_CCM_C) if (todo.aes_ccm) { int keysize; mbedtls_ccm_context ccm; mbedtls_ccm_init(&ccm); for (keysize = 128; keysize <= 256; keysize += 64) { mbedtls_snprintf(title, sizeof(title), "AES-CCM-%d", keysize); memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); mbedtls_ccm_setkey(&ccm, MBEDTLS_CIPHER_ID_AES, tmp, keysize); TIME_AND_TSC(title, mbedtls_ccm_encrypt_and_tag(&ccm, BUFSIZE, tmp, 12, NULL, 0, buf, buf, tmp, 16)); mbedtls_ccm_free(&ccm); } } #endif #if defined(MBEDTLS_CMAC_C) if (todo.aes_cmac) { unsigned char output[16]; const mbedtls_cipher_info_t *cipher_info; mbedtls_cipher_type_t cipher_type; int keysize; for (keysize = 128, cipher_type = MBEDTLS_CIPHER_AES_128_ECB; keysize <= 256; keysize += 64, cipher_type++) { mbedtls_snprintf(title, sizeof(title), "AES-CMAC-%d", keysize); memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); cipher_info = mbedtls_cipher_info_from_type(cipher_type); TIME_AND_TSC(title, mbedtls_cipher_cmac(cipher_info, tmp, keysize, buf, BUFSIZE, output)); } memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); TIME_AND_TSC("AES-CMAC-PRF-128", mbedtls_aes_cmac_prf_128(tmp, 16, buf, BUFSIZE, output)); } #endif /* MBEDTLS_CMAC_C */ #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_CAMELLIA_C) && defined(MBEDTLS_CIPHER_MODE_CBC) if (todo.camellia) { int keysize; mbedtls_camellia_context camellia; mbedtls_camellia_init(&camellia); for (keysize = 128; keysize <= 256; keysize += 64) { mbedtls_snprintf(title, sizeof(title), "CAMELLIA-CBC-%d", keysize); memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); mbedtls_camellia_setkey_enc(&camellia, tmp, keysize); TIME_AND_TSC(title, mbedtls_camellia_crypt_cbc(&camellia, MBEDTLS_CAMELLIA_ENCRYPT, BUFSIZE, tmp, buf, buf)); } mbedtls_camellia_free(&camellia); } #endif #if defined(MBEDTLS_BLOWFISH_C) && defined(MBEDTLS_CIPHER_MODE_CBC) if (todo.blowfish) { int keysize; mbedtls_blowfish_context blowfish; mbedtls_blowfish_init(&blowfish); for (keysize = 128; keysize <= 256; keysize += 64) { mbedtls_snprintf(title, sizeof(title), "BLOWFISH-CBC-%d", keysize); memset(buf, 0, sizeof(buf)); memset(tmp, 0, sizeof(tmp)); mbedtls_blowfish_setkey(&blowfish, tmp, keysize); TIME_AND_TSC(title, mbedtls_blowfish_crypt_cbc(&blowfish, MBEDTLS_BLOWFISH_ENCRYPT, BUFSIZE, tmp, buf, buf)); } mbedtls_blowfish_free(&blowfish); } #endif #if defined(MBEDTLS_HAVEGE_C) if (todo.havege) { mbedtls_havege_state hs; mbedtls_havege_init(&hs); TIME_AND_TSC("HAVEGE", mbedtls_havege_random(&hs, buf, BUFSIZE)); mbedtls_havege_free(&hs); } #endif #if defined(MBEDTLS_CTR_DRBG_C) if (todo.ctr_drbg) { mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ctr_drbg_init(&ctr_drbg); if (mbedtls_ctr_drbg_seed(&ctr_drbg, myrand, NULL, NULL, 0) != 0) { mbedtls_exit(1); } TIME_AND_TSC("CTR_DRBG (NOPR)", if (mbedtls_ctr_drbg_random(&ctr_drbg, buf, BUFSIZE) != 0) mbedtls_exit(1)); if (mbedtls_ctr_drbg_seed(&ctr_drbg, myrand, NULL, NULL, 0) != 0) { mbedtls_exit(1); } mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON); TIME_AND_TSC("CTR_DRBG (PR)", if (mbedtls_ctr_drbg_random(&ctr_drbg, buf, BUFSIZE) != 0) mbedtls_exit(1)); mbedtls_ctr_drbg_free(&ctr_drbg); }
int example(void) { printf( "\r\n\r\n" ); /* * Method 1: use all-in-one function of a specific SHA-xxx module */ unsigned char output1[32]; /* SHA-256 outputs 32 bytes */ /* 0 here means use the full SHA-256, not the SHA-224 variant */ mbedtls_sha256(hello_buffer, hello_len, output1, 0); print_hex("Method 1", output1, sizeof output1); /* * Method 2: use the streaming interface of a specific SHA-xxx module * This is useful if we get our input piecewise. */ unsigned char output2[32]; mbedtls_sha256_context ctx2; mbedtls_sha256_init(&ctx2); mbedtls_sha256_starts(&ctx2, 0); /* SHA-256, not 224 */ /* Simulating multiple fragments */ mbedtls_sha256_update(&ctx2, hello_buffer, 1); mbedtls_sha256_update(&ctx2, hello_buffer + 1, 1); mbedtls_sha256_update(&ctx2, hello_buffer + 2, hello_len - 2); mbedtls_sha256_finish(&ctx2, output2); print_hex("Method 2", output2, sizeof output2); /* Or you could re-use the context by doing mbedtls_sha256_starts() again */ mbedtls_sha256_free(&ctx2); /* * Method 3: use all-in-one function of the generice interface */ unsigned char output3[MBEDTLS_MD_MAX_SIZE]; /* Enough for any hash */ /* Can easily pick any hash you want, by identifier */ const mbedtls_md_info_t *md_info3 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); if (md_info3 == NULL) { printf("SHA256 not available\r\n"); return 1; } int ret3 = mbedtls_md(md_info3, hello_buffer, hello_len, output3); if (ret3 != 0) { printf("md() returned -0x%04X\r\n", -ret3); return 1; } print_hex("Method 3", output3, mbedtls_md_get_size(md_info3)); /* * Method 4: streaming & generic interface */ unsigned char output4[MBEDTLS_MD_MAX_SIZE]; /* Enough for any hash */ const mbedtls_md_info_t *md_info4 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); if (md_info4 == NULL) { printf("SHA256 not available\r\n"); return 1; } mbedtls_md_context_t ctx4; mbedtls_md_init(&ctx4); int ret4 = mbedtls_md_init_ctx(&ctx4, md_info4); if (ret4 != 0) { printf("md_init_ctx() returned -0x%04X\r\n", -ret4); return 1; } mbedtls_md_starts(&ctx4); /* Simulating multiple fragments */ mbedtls_md_update(&ctx4, hello_buffer, 1); mbedtls_md_update(&ctx4, hello_buffer + 1, 1); mbedtls_md_update(&ctx4, hello_buffer + 2, hello_len - 2); mbedtls_md_finish(&ctx4, output4); print_hex("Method 4", output4, mbedtls_md_get_size(md_info4)); /* Or you could re-use the context by doing mbedtls_md_starts() again */ mbedtls_md_free(&ctx4); printf("\r\nDONE\r\n"); return 0; }
int dslink_handshake_generate(Url *url, mbedtls_ecdh_context *key, const char *name, uint8_t isRequester, uint8_t isResponder, json_t **handshake, char **dsId) { *handshake = NULL; Socket *sock = NULL; char *resp = NULL; char *body = NULL; int ret = 0; unsigned char pubKeyBin[65]; size_t pubKeyBinLen = 0; unsigned char pubKey[90]; size_t pubKeyLen = 0; if ((errno = mbedtls_ecp_point_write_binary(&key->grp, &key->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &pubKeyBinLen, pubKeyBin, sizeof(pubKeyBin))) != 0) { ret = DSLINK_CRYPT_KEY_ENCODE_ERR; goto exit; } if ((errno = dslink_base64_url_encode(pubKey, sizeof(pubKey), &pubKeyLen, pubKeyBin, pubKeyBinLen)) != 0) { ret = DSLINK_CRYPT_BASE64_URL_ENCODE_ERR; goto exit; } { // Generate dsId unsigned char sha[32]; mbedtls_sha256(pubKeyBin, pubKeyBinLen, sha, 0); unsigned char tmp[45]; size_t tmpLen = 0; if ((errno = dslink_base64_url_encode((unsigned char *) tmp, sizeof(tmp), &tmpLen, sha, sizeof(sha))) != 0) { ret = DSLINK_CRYPT_BASE64_URL_ENCODE_ERR; goto exit; } size_t nameLen = strlen(name); *dsId = malloc(nameLen + tmpLen + 2); if (!(*dsId)) { ret = DSLINK_ALLOC_ERR; goto exit; } memcpy(*dsId, name, nameLen); *(*dsId + nameLen) = '-'; memcpy((*dsId + nameLen + 1), (char *) tmp, tmpLen); *(*dsId + nameLen + tmpLen + 1) = '\0'; } { // Create the request body json_t *obj = json_object(); if (!obj) { ret = DSLINK_ALLOC_ERR; goto exit; } json_object_set_new(obj, "publicKey", json_string((char *) pubKey)); json_object_set_new(obj, "isRequester", json_boolean(isRequester)); json_object_set_new(obj, "isResponder", json_boolean(isResponder)); json_object_set_new(obj, "version", json_string("1.1.2")); body = json_dumps(obj, JSON_INDENT(2)); json_delete(obj); if (!body) { ret = DSLINK_ALLOC_ERR; goto exit; } } char req[512]; size_t reqLen; { char uri[128]; snprintf(uri, sizeof(uri), "%s?dsId=%s", url->uri, *dsId); reqLen = snprintf(req, sizeof(req), DSLINK_POST_REQ, uri, url->host, url->port, (int) strlen(body), body); } if ((ret = dslink_socket_connect(&sock, url->host, url->port, url->secure)) != 0) { goto exit; } dslink_socket_write(sock, req, reqLen); int respLen = 0; while (1) { char buf[1024]; int read = dslink_socket_read(sock, buf, sizeof(buf) - 1); if (read <= 0) { break; } if (resp == NULL) { resp = malloc((size_t) read + 1); if (!resp) { ret = DSLINK_ALLOC_ERR; goto exit; } respLen = read; memcpy(resp, buf, read); *(resp + respLen) = '\0'; } else { char *tmp = realloc(resp, (size_t) respLen + read + 1); if (!tmp) { free(resp); ret = DSLINK_ALLOC_ERR; goto exit; } resp = tmp; memcpy(resp + respLen, buf, read); respLen += read; *(resp + respLen) = '\0'; } } if (!resp) { ret = DSLINK_HANDSHAKE_NO_RESPONSE; goto exit; } char *index = strstr(resp, "401 Unauthorized"); if (index) { ret = DSLINK_HANDSHAKE_UNAUTHORIZED; goto exit; } index = strchr(resp, '{'); if (!index) { ret = DSLINK_HANDSHAKE_INVALID_RESPONSE; goto exit; } char *json = index; index = strrchr(json, '}'); if (!index) { ret = DSLINK_HANDSHAKE_INVALID_RESPONSE; goto exit; } *(index + 1) = '\0'; json_error_t jsonErr; *handshake = json_loads(json, 0, &jsonErr); if (!(*handshake)) { ret = DSLINK_ALLOC_ERR; goto exit; } const char *id = json_string_value(json_object_get(*handshake, "id")); if (id) { free(*dsId); size_t size = strlen(id) + 1; *dsId = malloc(size); if (!(*dsId)) { ret = DSLINK_ALLOC_ERR; json_delete(*handshake); *handshake = NULL; goto exit; } memcpy(*dsId, id, size); } exit: DSLINK_CHECKED_EXEC(free, body); DSLINK_CHECKED_EXEC(free, resp); DSLINK_CHECKED_EXEC(dslink_socket_close, sock); return ret; }