@@ -2481,3 +2481,176 @@ int test_wc_AsnFeatureCoverage(void)
24812481#endif /* !NO_ASN && HAVE_ECC && USE_CERT_BUFFERS_256 && !HAVE_FIPS */
24822482 return EXPECT_RESULT ();
24832483}
2484+
2485+ #if defined(USE_WOLFSSL_MEMORY ) && !defined(WOLFSSL_NO_MALLOC ) && \
2486+ !defined(WOLFSSL_STATIC_MEMORY )
2487+ static int ecc_oom_failed = 0 ;
2488+ static int ecc_oom_inject = 0 ;
2489+
2490+ /* Custom malloc for testing OOM.
2491+ * Returns allocated pointer or NULL on failure. */
2492+ #ifdef WOLFSSL_DEBUG_MEMORY
2493+ static void * ecc_oom_malloc_cb (size_t size , const char * func ,
2494+ unsigned int line )
2495+ {
2496+ (void )func ;
2497+ (void )line ;
2498+ #else
2499+ static void * ecc_oom_malloc_cb (size_t size )
2500+ {
2501+ #endif
2502+ if (ecc_oom_inject && !ecc_oom_failed ) {
2503+ ecc_oom_failed = 1 ;
2504+ return NULL ;
2505+ }
2506+ return malloc (size );
2507+ }
2508+
2509+ /* Custom free for testing OOM. */
2510+ #ifdef WOLFSSL_DEBUG_MEMORY
2511+ static void ecc_oom_free_cb (void * ptr , const char * func , unsigned int line )
2512+ {
2513+ (void )func ;
2514+ (void )line ;
2515+ #else
2516+ static void ecc_oom_free_cb (void * ptr )
2517+ {
2518+ #endif
2519+ free (ptr );
2520+ }
2521+
2522+ /* Custom realloc for testing OOM.
2523+ * Returns reallocated pointer or NULL on failure. */
2524+ #ifdef WOLFSSL_DEBUG_MEMORY
2525+ static void * ecc_oom_realloc_cb (void * ptr , size_t size , const char * func ,
2526+ unsigned int line )
2527+ {
2528+ (void )func ;
2529+ (void )line ;
2530+ #else
2531+ static void * ecc_oom_realloc_cb (void * ptr , size_t size )
2532+ {
2533+ #endif
2534+ return realloc (ptr , size );
2535+ }
2536+ #endif /* USE_WOLFSSL_MEMORY */
2537+
2538+ /* wc_EccPrivateKeyDecode should derive and cache the public point (best
2539+ * effort) when it decodes a SEC1 private key whose optional public point
2540+ * was omitted, so the key comes out fully usable. */
2541+ int test_wc_EccPrivateKeyDecode_derive_pub (void )
2542+ {
2543+ EXPECT_DECLS ;
2544+ #if !defined(NO_ASN ) && defined(HAVE_ECC ) && !defined(NO_ECC_MAKE_PUB ) && \
2545+ defined(USE_CERT_BUFFERS_256 ) && !defined(HAVE_FIPS ) && \
2546+ !defined(WOLFSSL_ATECC508A ) && !defined(WOLFSSL_ATECC608A ) && \
2547+ !defined(WOLFSSL_MICROCHIP_TA100 ) && !defined(WOLFSSL_CRYPTOCELL ) && \
2548+ !defined(WOLFSSL_SILABS_SE_ACCEL ) && !defined(WOLFSSL_KCAPI_ECC ) && \
2549+ !defined(WOLFSSL_QNX_CAAM ) && !defined(WOLFSSL_IMXRT1170_CAAM )
2550+ ecc_key fullKey ;
2551+ ecc_key privOnlyKey ;
2552+ WC_RNG rng ;
2553+ word32 idx ;
2554+ byte privOnlyDer [256 ];
2555+ int privOnlyDerSz ;
2556+ byte fullPub [256 ];
2557+ word32 fullPubSz = sizeof (fullPub );
2558+ byte derivedPub [256 ];
2559+ word32 derivedPubSz = sizeof (derivedPub );
2560+
2561+ XMEMSET (& fullKey , 0 , sizeof (fullKey ));
2562+ XMEMSET (& privOnlyKey , 0 , sizeof (privOnlyKey ));
2563+
2564+ ExpectIntEQ (wc_InitRng (& rng ), 0 );
2565+
2566+ ExpectIntEQ (wc_ecc_init (& fullKey ), 0 );
2567+ idx = 0 ;
2568+ ExpectIntEQ (wc_EccPrivateKeyDecode (ecc_clikey_der_256 , & idx , & fullKey ,
2569+ sizeof_ecc_clikey_der_256 ), 0 );
2570+ ExpectIntEQ (fullKey .type , ECC_PRIVATEKEY );
2571+ PRIVATE_KEY_UNLOCK ();
2572+ ExpectIntEQ (wc_ecc_export_x963 (& fullKey , fullPub , & fullPubSz ), 0 );
2573+ PRIVATE_KEY_LOCK ();
2574+
2575+ /* Re-encode as a private-key-only SEC1 DER (no public point). */
2576+ ExpectIntGT (privOnlyDerSz = wc_EccPrivateKeyToDer (& fullKey , privOnlyDer ,
2577+ sizeof (privOnlyDer )), 0 );
2578+
2579+ #ifdef ECC_TIMING_RESISTANT
2580+ /* Without an RNG set, decode must not derive unblinded: the key is
2581+ * left as ECC_PRIVATEKEY_ONLY, same as before auto-derivation existed. */
2582+ ExpectIntEQ (wc_ecc_init (& privOnlyKey ), 0 );
2583+ idx = 0 ;
2584+ ExpectIntEQ (wc_EccPrivateKeyDecode (privOnlyDer , & idx , & privOnlyKey ,
2585+ (word32 )privOnlyDerSz ), 0 );
2586+ ExpectIntEQ (privOnlyKey .type , ECC_PRIVATEKEY_ONLY );
2587+ wc_ecc_free (& privOnlyKey );
2588+ #endif
2589+
2590+ /* Opting into blinding (as every other blinded ECC op in this library
2591+ * requires) makes decode derive and cache the public point. */
2592+ ExpectIntEQ (wc_ecc_init (& privOnlyKey ), 0 );
2593+ ExpectIntEQ (wc_ecc_set_rng (& privOnlyKey , & rng ), 0 );
2594+ idx = 0 ;
2595+ ExpectIntEQ (wc_EccPrivateKeyDecode (privOnlyDer , & idx , & privOnlyKey ,
2596+ (word32 )privOnlyDerSz ), 0 );
2597+
2598+ /* The public point should have been derived automatically, making the
2599+ * key fully usable rather than left as ECC_PRIVATEKEY_ONLY. */
2600+ ExpectIntEQ (privOnlyKey .type , ECC_PRIVATEKEY );
2601+ PRIVATE_KEY_UNLOCK ();
2602+ ExpectIntEQ (wc_ecc_export_x963 (& privOnlyKey , derivedPub , & derivedPubSz ),
2603+ 0 );
2604+ PRIVATE_KEY_LOCK ();
2605+ ExpectIntEQ (derivedPubSz , fullPubSz );
2606+ ExpectBufEQ (derivedPub , fullPub , fullPubSz );
2607+
2608+ wc_ecc_free (& privOnlyKey );
2609+ wc_ecc_free (& fullKey );
2610+
2611+ #if defined(USE_WOLFSSL_MEMORY ) && !defined(WOLFSSL_NO_MALLOC ) && \
2612+ !defined(WOLFSSL_STATIC_MEMORY )
2613+ {
2614+ wolfSSL_Malloc_cb prevMalloc = NULL ;
2615+ wolfSSL_Free_cb prevFree = NULL ;
2616+ wolfSSL_Realloc_cb prevRealloc = NULL ;
2617+ int allocatorsSet = 0 ;
2618+
2619+ ExpectIntEQ (wolfSSL_GetAllocators (& prevMalloc , & prevFree , & prevRealloc ),
2620+ 0 );
2621+ ExpectIntEQ (wolfSSL_SetAllocators (ecc_oom_malloc_cb , ecc_oom_free_cb ,
2622+ ecc_oom_realloc_cb ), 0 );
2623+ if (EXPECT_SUCCESS ()) {
2624+ allocatorsSet = 1 ;
2625+ }
2626+
2627+ /* Test that a derivation failure leaves the key as ECC_PRIVATEKEY_ONLY
2628+ * but does not fail the overall decode. */
2629+ ecc_oom_failed = 0 ;
2630+
2631+ ExpectIntEQ (wc_ecc_init (& privOnlyKey ), 0 );
2632+ ExpectIntEQ (wc_ecc_set_rng (& privOnlyKey , & rng ), 0 );
2633+
2634+ idx = 0 ;
2635+ /* Start injecting only once decode itself begins. */
2636+ ecc_oom_inject = 1 ;
2637+ /* Decode should succeed, but leave the key as ECC_PRIVATEKEY_ONLY. */
2638+ ExpectIntEQ (wc_EccPrivateKeyDecode (privOnlyDer , & idx , & privOnlyKey ,
2639+ (word32 )privOnlyDerSz ), 0 );
2640+ ExpectIntEQ (ecc_oom_failed , 1 );
2641+ ExpectIntEQ (privOnlyKey .type , ECC_PRIVATEKEY_ONLY );
2642+
2643+ wc_ecc_free (& privOnlyKey );
2644+ ecc_oom_inject = 0 ;
2645+
2646+ if (allocatorsSet ) {
2647+ (void )wolfSSL_SetAllocators (prevMalloc , prevFree , prevRealloc );
2648+ }
2649+ }
2650+ #endif /* USE_WOLFSSL_MEMORY */
2651+
2652+ wc_FreeRng (& rng );
2653+ #endif /* !NO_ASN && HAVE_ECC && !NO_ECC_MAKE_PUB && USE_CERT_BUFFERS_256 &&
2654+ * !HAVE_FIPS */
2655+ return EXPECT_RESULT ();
2656+ }
0 commit comments