package org.bouncycastle.tls.crypto;

import java.io.IOException;

import org.bouncycastle.tls.TlsUtils;
import org.bouncycastle.util.Strings;

public abstract class TlsCryptoUtils
{
    public static TlsSecret hkdfExpandLabel(TlsSecret secret, short hashAlgorithm, String label, byte[] context, int length)
        throws IOException
    {
        byte[] expandedLabel = Strings.toByteArray("tls13 " + label);

        byte[] hkdfLabel = new byte[2 + (1 + expandedLabel.length) + (1 + context.length)];

        TlsUtils.checkUint16(length);
        TlsUtils.writeUint16(length, hkdfLabel, 0);

        TlsUtils.writeOpaque8(expandedLabel, hkdfLabel, 2);

        TlsUtils.writeOpaque8(context, hkdfLabel, 2 + (1 + expandedLabel.length));

        return secret.hkdfExpand(hashAlgorithm, hkdfLabel, length);
    }
}

@@ -88,24 +88,75 @@
 tle.tls.
-TlsUtils
+AlertDescription;%0Aimport org.bouncycastle.tls.TlsFatalAlert
 ;%0Aimport
@@ -177,19 +177,19 @@
 tle.
-util.String
+tls.TlsUtil
 s;%0A%0A
@@ -227,16 +227,130 @@
 Utils%0A%7B%0A
+    // %22tls13 %22%0A    private static final byte%5B%5D TLS13_PREFIX = new byte%5B%5D%7B 0x74, 0x6c, 0x73, 0x31, 0x33, 0x20 %7D;%0A%0A
     publ
@@ -511,67 +511,267 @@
     
-byte%5B%5D expandedLabel = Strings.toByteArray(%22tls13 %22
+int labelLength = label.length();%0A        if (labelLength %3C 1)%0A        %7B%0A            throw new TlsFatalAlert(AlertDescription.internal_error);%0A        %7D%0A%0A        int contextLength = context.length;%0A        int expandedLabelLength = TLS13_PREFIX.length
  + label
 );%0A%0A
@@ -766,17 +766,22 @@
  + label
-)
+Length
 ;%0A%0A     
@@ -829,26 +829,25 @@
 xpandedLabel
-.l
+L
 ength) + (1 
@@ -851,26 +851,25 @@
 (1 + context
-.l
+L
 ength)%5D;%0A%0A  
@@ -866,16 +866,55 @@
 gth)%5D;%0A%0A
+        // uint16 length%0A        %7B%0A    
         
@@ -939,24 +939,28 @@
 16(length);%0A
+    
         TlsU
@@ -1003,37 +1003,145 @@
 0);%0A
-%0A        TlsUtils.writeOpaque
+        %7D%0A%0A        // opaque label%3C7..255%3E%0A        %7B%0A            TlsUtils.checkUint8(expandedLabelLength);%0A            TlsUtils.writeUint
 8(ex
@@ -1151,16 +1151,22 @@
 dedLabel
+Length
 , hkdfLa
@@ -1171,24 +1171,384 @@
 Label, 2);%0A%0A
+            System.arraycopy(TLS13_PREFIX, 0, hkdfLabel, 2 + 1, TLS13_PREFIX.length);%0A%0A            int labelPos = 2 + (1 + TLS13_PREFIX.length);%0A            for (int i = 0; i %3C labelLength; ++i)%0A            %7B%0A                char c = label.charAt(i);%0A                hkdfLabel%5BlabelPos + i%5D = (byte)c;%0A            %7D%0A        %7D%0A%0A        // context%0A        %7B%0A    
         TlsU
@@ -1611,18 +1611,17 @@
 abel
-.l
+L
 ength));
 %0A%0A  
@@ -1616,16 +1616,26 @@
 ength));
+%0A        %7D
 %0A%0A      

Avoid string concat, convert in place