diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index b0fb5a883..010c338c0 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -3275,7 +3275,9 @@ psa_status_t psa_generator_abort( psa_crypto_generator_t *generator )
         mbedtls_free( generator->ctx.hkdf.info );
         status = psa_hmac_abort_internal( &generator->ctx.hkdf.hmac );
     }
-    else if( PSA_ALG_IS_TLS12_PRF( generator->alg ) )
+    else if( PSA_ALG_IS_TLS12_PRF( generator->alg ) ||
+             /* TLS-1.2 PSK-to-MS KDF uses the same generator as TLS-1.2 PRF */
+             PSA_ALG_IS_TLS12_PSK_TO_MS( generator->alg ) )
     {
         if( generator->ctx.tls12_prf.key != NULL )
         {
@@ -3578,7 +3580,8 @@ psa_status_t psa_generator_read( psa_crypto_generator_t *generator,
         status = psa_generator_hkdf_read( &generator->ctx.hkdf, hash_alg,
                                           output, output_length );
     }
-    else if( PSA_ALG_IS_TLS12_PRF( generator->alg ) )
+    else if( PSA_ALG_IS_TLS12_PRF( generator->alg ) ||
+             PSA_ALG_IS_TLS12_PSK_TO_MS( generator->alg ) )
     {
         status = psa_generator_tls12_prf_read( &generator->ctx.tls12_prf,
                                                generator->alg, output,
@@ -3749,6 +3752,47 @@ static psa_status_t psa_generator_tls12_prf_setup(
 
     return( PSA_SUCCESS );
 }
+
+/* Set up a TLS-1.2-PSK-to-MS-based generator. */
+static psa_status_t psa_generator_tls12_psk_to_ms_setup(
+    psa_tls12_prf_generator_t *tls12_prf,
+    const unsigned char *psk,
+    size_t psk_len,
+    psa_algorithm_t hash_alg,
+    const uint8_t *salt,
+    size_t salt_length,
+    const uint8_t *label,
+    size_t label_length )
+{
+    psa_status_t status;
+    unsigned char pms[ 4 + 2 * PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ];
+
+    if( psk_len > PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    /* Quoting RFC 4279, Section 2:
+     *
+     * The premaster secret is formed as follows: if the PSK is N octets
+     * long, concatenate a uint16 with the value N, N zero octets, a second
+     * uint16 with the value N, and the PSK itself.
+     */
+
+    pms[0] = ( psk_len >> 8 ) & 0xff;
+    pms[1] = ( psk_len >> 0 ) & 0xff;
+    memset( pms + 2, 0, psk_len );
+    pms[2 + psk_len + 0] = pms[0];
+    pms[2 + psk_len + 1] = pms[1];
+    memcpy( pms + 4 + psk_len, psk, psk_len );
+
+    status = psa_generator_tls12_prf_setup( tls12_prf,
+                                            pms, 4 + 2 * psk_len,
+                                            hash_alg,
+                                            salt, salt_length,
+                                            label, label_length );
+
+    mbedtls_zeroize( pms, sizeof( pms ) );
+    return( status );
+}
 #endif /* MBEDTLS_MD_C */
 
 /* Note that if this function fails, you must call psa_generator_abort()
@@ -3799,7 +3843,9 @@ static psa_status_t psa_key_derivation_internal(
                                            salt, salt_length,
                                            label, label_length );
     }
-    else if( PSA_ALG_IS_TLS12_PRF( alg ) )
+    /* TLS-1.2 PRF and TLS-1.2 PSK-to-MS are very similar, so share code. */
+    else if( PSA_ALG_IS_TLS12_PRF( alg ) ||
+             PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
     {
         psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH( alg );
         size_t hash_size = PSA_HASH_SIZE( hash_alg );
@@ -3812,10 +3858,22 @@ static psa_status_t psa_key_derivation_internal(
         }
 
         max_capacity = 255 * hash_size;
-        status = psa_generator_tls12_prf_setup( &generator->ctx.tls12_prf,
-                                                secret, secret_length,
-                                                hash_alg, salt, salt_length,
-                                                label, label_length );
+
+        if( PSA_ALG_IS_TLS12_PRF( alg ) )
+        {
+            status = psa_generator_tls12_prf_setup( &generator->ctx.tls12_prf,
+                                                    secret, secret_length,
+                                                    hash_alg, salt, salt_length,
+                                                    label, label_length );
+        }
+        else
+        {
+            status = psa_generator_tls12_psk_to_ms_setup(
+                &generator->ctx.tls12_prf,
+                secret, secret_length,
+                hash_alg, salt, salt_length,
+                label, label_length );
+        }
     }
     else
 #endif