@@ -89,6 +89,16 @@ static int _RsaMakeKey(whClientContext* ctx, uint32_t size, uint32_t e,
8989 whKeyId * inout_key_id , RsaKey * rsa );
9090#endif
9191
92+ #ifdef HAVE_HKDF
93+ /* Generate HKDF output on the server based on the flags */
94+ static int _HkdfMakeKey (whClientContext * ctx , int hashType ,
95+ const uint8_t * inKey , uint32_t inKeySz ,
96+ const uint8_t * salt , uint32_t saltSz ,
97+ const uint8_t * info , uint32_t infoSz , whNvmFlags flags ,
98+ uint32_t label_len , const uint8_t * label ,
99+ whKeyId * inout_key_id , uint8_t * out , uint32_t outSz );
100+ #endif
101+
92102#ifdef HAVE_DILITHIUM
93103/* Make a ML-DSA key on the server based on the flags */
94104static int _MlDsaMakeKey (whClientContext * ctx , int size , int level ,
@@ -2282,6 +2292,180 @@ int wh_Client_RsaGetSize(whClientContext* ctx, const RsaKey* key, int* out_size)
22822292
22832293#endif /* !NO_RSA */
22842294
2295+ #ifdef HAVE_HKDF
2296+ /* Internal helper function to generate HKDF output on the server */
2297+ static int _HkdfMakeKey (whClientContext * ctx , int hashType ,
2298+ const uint8_t * inKey , uint32_t inKeySz ,
2299+ const uint8_t * salt , uint32_t saltSz ,
2300+ const uint8_t * info , uint32_t infoSz , whNvmFlags flags ,
2301+ uint32_t label_len , const uint8_t * label ,
2302+ whKeyId * inout_key_id , uint8_t * out , uint32_t outSz )
2303+ {
2304+ int ret = WH_ERROR_OK ;
2305+ uint8_t * dataPtr = NULL ;
2306+ whMessageCrypto_HkdfRequest * req = NULL ;
2307+ whMessageCrypto_HkdfResponse * res = NULL ;
2308+ uint16_t group = WH_MESSAGE_GROUP_CRYPTO ;
2309+ uint16_t action = WC_ALGO_TYPE_KDF ;
2310+ whKeyId key_id = WH_KEYID_ERASED ;
2311+
2312+ if ((ctx == NULL ) || (inKey == NULL )) {
2313+ return WH_ERROR_BADARGS ;
2314+ }
2315+
2316+ /* Get data pointer from the context to use as request/response storage */
2317+ dataPtr = wh_CommClient_GetDataPtr (ctx -> comm );
2318+ if (dataPtr == NULL ) {
2319+ return WH_ERROR_BADARGS ;
2320+ }
2321+
2322+ /* Setup generic header and get pointer to request data */
2323+ req = (whMessageCrypto_HkdfRequest * )_createCryptoRequest (dataPtr ,
2324+ WC_ALGO_TYPE_KDF );
2325+
2326+ /* Calculate request length including variable-length data */
2327+ uint16_t req_len = sizeof (whMessageCrypto_GenericRequestHeader ) +
2328+ sizeof (* req ) + inKeySz + saltSz + infoSz ;
2329+
2330+ /* Use the supplied key id if provided */
2331+ if (inout_key_id != NULL ) {
2332+ key_id = * inout_key_id ;
2333+ }
2334+
2335+ /* Populate request body */
2336+ req -> flags = flags ;
2337+ req -> keyId = key_id ;
2338+ req -> hashType = hashType ;
2339+ req -> inKeySz = inKeySz ;
2340+ req -> saltSz = saltSz ;
2341+ req -> infoSz = infoSz ;
2342+ req -> outSz = outSz ;
2343+
2344+ /* Copy label if provided */
2345+ if ((label != NULL ) && (label_len > 0 )) {
2346+ if (label_len > WH_NVM_LABEL_LEN ) {
2347+ label_len = WH_NVM_LABEL_LEN ;
2348+ }
2349+ memcpy (req -> label , label , label_len );
2350+ if (label_len < WH_NVM_LABEL_LEN ) {
2351+ req -> label [label_len ] = '\0' ;
2352+ }
2353+ }
2354+ else {
2355+ memset (req -> label , 0 , WH_NVM_LABEL_LEN );
2356+ }
2357+
2358+ /* Copy variable-length data after the request structure */
2359+ uint8_t * data_ptr = (uint8_t * )(req + 1 );
2360+
2361+ /* Copy input key material */
2362+ memcpy (data_ptr , inKey , inKeySz );
2363+ data_ptr += inKeySz ;
2364+
2365+ /* Copy salt if provided */
2366+ if (salt != NULL && saltSz > 0 ) {
2367+ memcpy (data_ptr , salt , saltSz );
2368+ data_ptr += saltSz ;
2369+ }
2370+
2371+ /* Copy info if provided */
2372+ if (info != NULL && infoSz > 0 ) {
2373+ memcpy (data_ptr , info , infoSz );
2374+ }
2375+
2376+ /* Send Request */
2377+ ret = wh_Client_SendRequest (ctx , group , action , req_len , dataPtr );
2378+
2379+ #ifdef DEBUG_CRYPTOCB_VERBOSE
2380+ printf ("HKDF Req sent: hashType:%d inKeySz:%u saltSz:%u infoSz:%u outSz:%u "
2381+ "ret:%d\n" ,
2382+ req -> hashType , req -> inKeySz , req -> saltSz , req -> infoSz , req -> outSz ,
2383+ ret );
2384+ #endif
2385+
2386+ if (ret == 0 ) {
2387+ uint16_t res_len = 0 ;
2388+ do {
2389+ ret =
2390+ wh_Client_RecvResponse (ctx , & group , & action , & res_len , dataPtr );
2391+ } while (ret == WH_ERROR_NOTREADY );
2392+
2393+ #ifdef DEBUG_CRYPTOCB_VERBOSE
2394+ printf ("HKDF Res recv: ret:%d, res_len: %u\n" , ret , res_len );
2395+ #endif
2396+
2397+ if (ret == WH_ERROR_OK ) {
2398+ /* Get response structure pointer, validates generic header rc */
2399+ ret =
2400+ _getCryptoResponse (dataPtr , WC_ALGO_TYPE_KDF , (uint8_t * * )& res );
2401+ }
2402+
2403+ if (ret == WH_ERROR_OK ) {
2404+ /* Key is cached on server or is ephemeral */
2405+ key_id = (whKeyId )(res -> keyId );
2406+
2407+ /* Update output variable if requested */
2408+ if (inout_key_id != NULL ) {
2409+ * inout_key_id = key_id ;
2410+ }
2411+
2412+ /* Copy output key material if output buffer provided */
2413+ if (out != NULL ) {
2414+ if (res -> outSz <= outSz ) {
2415+ uint8_t * hkdf_out = (uint8_t * )(res + 1 );
2416+ memcpy (out , hkdf_out , res -> outSz );
2417+
2418+ #ifdef DEBUG_CRYPTOCB_VERBOSE
2419+ printf ("[client] %s Set key_id:%x with flags:%x outSz:%u\n" ,
2420+ __func__ , key_id , flags , res -> outSz );
2421+ #endif
2422+ }
2423+ else {
2424+ /* Server returned more than we can handle - error */
2425+ ret = WH_ERROR_ABORTED ;
2426+ }
2427+ }
2428+ }
2429+ }
2430+ return ret ;
2431+ }
2432+
2433+ int wh_Client_HkdfMakeCacheKey (whClientContext * ctx , int hashType ,
2434+ const uint8_t * inKey , uint32_t inKeySz ,
2435+ const uint8_t * salt , uint32_t saltSz ,
2436+ const uint8_t * info , uint32_t infoSz ,
2437+ whKeyId * inout_key_id , whNvmFlags flags ,
2438+ const uint8_t * label , uint32_t label_len ,
2439+ uint32_t outSz )
2440+ {
2441+ /* Valid ctx and keyid ptr are required in this form */
2442+ if ((ctx == NULL ) || (inout_key_id == NULL )) {
2443+ return WH_ERROR_BADARGS ;
2444+ }
2445+
2446+ return _HkdfMakeKey (ctx , hashType , inKey , inKeySz , salt , saltSz , info ,
2447+ infoSz , flags , label_len , label , inout_key_id , NULL ,
2448+ outSz );
2449+ }
2450+
2451+ int wh_Client_HkdfMakeExportKey (whClientContext * ctx , int hashType ,
2452+ const uint8_t * inKey , uint32_t inKeySz ,
2453+ const uint8_t * salt , uint32_t saltSz ,
2454+ const uint8_t * info , uint32_t infoSz ,
2455+ uint8_t * out , uint32_t outSz )
2456+ {
2457+ /* Valid ctx and out are required for this form */
2458+ if ((ctx == NULL ) || (out == NULL )) {
2459+ return WH_ERROR_BADARGS ;
2460+ }
2461+
2462+ return _HkdfMakeKey (ctx , hashType , inKey , inKeySz , salt , saltSz , info ,
2463+ infoSz , WH_NVM_FLAGS_EPHEMERAL , 0 , NULL , NULL , out ,
2464+ outSz );
2465+ }
2466+
2467+ #endif /* HAVE_HKDF */
2468+
22852469#ifndef NO_AES
22862470int wh_Client_AesSetKeyId (Aes * key , whNvmId keyId )
22872471{
0 commit comments