diff --git a/tests/api.c b/tests/api.c index 47c9ac115..6d28ac64d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -32105,6 +32105,789 @@ static int test_wc_dilithium_check_key(void) return EXPECT_RESULT(); } +#if defined(HAVE_DILITHIUM) && defined(WOLFSSL_WC_DILITHIUM) && \ + defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) +static const unsigned char dilithium_public_der[] = { +#ifndef WOLFSSL_NO_ML_DSA_44 + 0x30, 0x82, 0x05, 0x34, 0x30, 0x0d, 0x06, 0x0b, + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0b, + 0x0c, 0x04, 0x04, 0x03, 0x82, 0x05, 0x21, 0x00, + 0x0a, 0xf7, 0xc8, 0xa4, 0x96, 0x01, 0xa7, 0xb2, + 0x2e, 0x4d, 0xc9, 0xd9, 0x1c, 0xa1, 0x86, 0x09, + 0xce, 0x14, 0x6f, 0xe8, 0x33, 0x3c, 0x7b, 0xdb, + 0x19, 0x9c, 0x56, 0x39, 0x6a, 0x6c, 0x5d, 0x1f, + 0xe4, 0x26, 0xcb, 0x16, 0x91, 0x4d, 0xeb, 0x5a, + 0x36, 0x22, 0xee, 0xda, 0xdf, 0x46, 0x3e, 0xa1, + 0x4f, 0x9a, 0x30, 0xb5, 0x3f, 0x60, 0xf7, 0x75, + 0x47, 0xdc, 0x55, 0xf1, 0xbe, 0xbc, 0x87, 0x6c, + 0x50, 0x7c, 0x21, 0x55, 0x35, 0xad, 0xa7, 0xf9, + 0x1c, 0xf8, 0xa1, 0x92, 0x79, 0x10, 0x52, 0x7a, + 0xc3, 0xba, 0xd3, 0x9d, 0xc6, 0x9b, 0xf4, 0xcb, + 0x1b, 0xa2, 0xde, 0x83, 0x86, 0xa6, 0x35, 0xea, + 0xf2, 0x8c, 0xdc, 0xba, 0x3e, 0xef, 0x9c, 0xf5, + 0x8e, 0xc3, 0xb0, 0xc0, 0x5b, 0xcc, 0x35, 0x6a, + 0x81, 0xe5, 0x17, 0xb3, 0x9a, 0x57, 0xa6, 0x4a, + 0x87, 0xb1, 0xa7, 0xf5, 0xa2, 0x96, 0x40, 0x8b, + 0xc1, 0x62, 0xb2, 0xd9, 0x76, 0xe8, 0x51, 0x33, + 0x44, 0x3d, 0xeb, 0x14, 0x86, 0x88, 0x2c, 0xc1, + 0x47, 0xba, 0x2b, 0x85, 0x3b, 0x72, 0xcb, 0x9f, + 0x40, 0xba, 0x19, 0x58, 0xa4, 0x34, 0x0a, 0xd2, + 0x8c, 0x97, 0xbd, 0x3d, 0x09, 0xb0, 0x4a, 0xeb, + 0xaa, 0xee, 0x58, 0x1e, 0xc1, 0x19, 0x26, 0x70, + 0x15, 0xa5, 0x17, 0x7e, 0xd0, 0xa1, 0x08, 0xf9, + 0x6d, 0xcf, 0x20, 0x62, 0x95, 0x8e, 0x61, 0xf4, + 0x29, 0x96, 0x6f, 0x38, 0x1c, 0x67, 0xd5, 0xa6, + 0x4c, 0xf5, 0x1f, 0xda, 0x12, 0x22, 0x24, 0x6b, + 0x0d, 0xb7, 0x6a, 0xe5, 0xaf, 0x6c, 0x89, 0x52, + 0xc2, 0x85, 0x85, 0x5f, 0x16, 0x33, 0x0c, 0xc6, + 0x7a, 0xe0, 0xa8, 0xed, 0x13, 0x58, 0xf3, 0xa0, + 0x80, 0x42, 0x3c, 0xe3, 0x57, 0xd1, 0xe2, 0x66, + 0xc4, 0xe0, 0x3d, 0x49, 0x32, 0x21, 0xd9, 0xa1, + 0x3c, 0x93, 0x0a, 0xf7, 0x5f, 0x34, 0x65, 0xa4, + 0x30, 0xf9, 0xe7, 0x8a, 0x96, 0x04, 0xdb, 0xc5, + 0x16, 0x15, 0x10, 0x74, 0x4f, 0xc9, 0x6b, 0x4b, + 0x66, 0x29, 0xb0, 0xd1, 0x3b, 0xdd, 0x41, 0x0a, + 0xfe, 0xdf, 0x5f, 0x72, 0x91, 0xbc, 0x99, 0x2f, + 0x8d, 0x72, 0x3a, 0x4a, 0xde, 0x11, 0x3a, 0x20, + 0xb2, 0x56, 0xb5, 0x73, 0x89, 0xb4, 0x63, 0x37, + 0x86, 0xbd, 0x99, 0x8b, 0x03, 0x56, 0x50, 0x21, + 0x11, 0x78, 0x8c, 0xd5, 0xc1, 0x92, 0x33, 0x72, + 0x6e, 0x8d, 0x88, 0x2d, 0x10, 0x8f, 0x31, 0xd3, + 0x23, 0xe5, 0xaa, 0x1f, 0xe1, 0x37, 0xec, 0x34, + 0x42, 0x30, 0x75, 0xff, 0xb2, 0x1a, 0x8e, 0x29, + 0x03, 0x4c, 0xfd, 0xdf, 0x53, 0xf2, 0x0b, 0x2d, + 0xf9, 0x1c, 0x9e, 0xb6, 0x5a, 0x6c, 0x5e, 0x88, + 0x48, 0x29, 0x89, 0x42, 0xfc, 0x97, 0xfb, 0x27, + 0x1c, 0x99, 0x2a, 0xbf, 0x7f, 0x04, 0xb2, 0xcd, + 0xc9, 0x3a, 0x39, 0xfe, 0x4f, 0x47, 0x92, 0x0b, + 0x85, 0xfc, 0x92, 0x57, 0xc5, 0x0b, 0x23, 0x1f, + 0x0b, 0x72, 0xb4, 0xde, 0xfe, 0xbe, 0xb7, 0x39, + 0xb3, 0xd7, 0x48, 0x03, 0xed, 0x76, 0xac, 0x63, + 0xf7, 0x2a, 0x58, 0xef, 0xdb, 0x63, 0x5a, 0x56, + 0x68, 0xcc, 0xb2, 0x8b, 0x22, 0xac, 0xdf, 0xc4, + 0xad, 0x6f, 0xad, 0x24, 0xfd, 0x30, 0xfb, 0xed, + 0x6e, 0xde, 0x65, 0x2b, 0xb4, 0x57, 0x35, 0x49, + 0xc1, 0xc9, 0x82, 0xf4, 0x72, 0x69, 0xef, 0x34, + 0xc0, 0x37, 0x8b, 0x8b, 0xd3, 0xd3, 0x25, 0xcc, + 0xe5, 0xf5, 0xf6, 0x9c, 0xa3, 0xe7, 0x88, 0xd7, + 0x55, 0x73, 0x31, 0x4c, 0xb1, 0x7b, 0x64, 0xb3, + 0x38, 0xde, 0x47, 0x9a, 0xfc, 0xf1, 0xfa, 0xf8, + 0x6e, 0xc5, 0x95, 0xb9, 0xaf, 0x6a, 0x7a, 0x94, + 0x80, 0x0d, 0x29, 0x62, 0x99, 0x0a, 0x34, 0xa2, + 0x8f, 0xa1, 0x5e, 0x98, 0x7c, 0x4e, 0x18, 0xcd, + 0x63, 0x68, 0x0e, 0xfa, 0x6f, 0x49, 0x01, 0x02, + 0xcd, 0xf1, 0xc1, 0x09, 0x57, 0xa3, 0x03, 0xec, + 0x94, 0x36, 0xab, 0xc6, 0x1c, 0xc0, 0x98, 0x22, + 0x15, 0x5b, 0x5b, 0x61, 0x3c, 0xc2, 0x5b, 0x6f, + 0x1c, 0x82, 0x41, 0x39, 0x87, 0xde, 0x92, 0xa9, + 0xe4, 0x12, 0x74, 0x3b, 0x31, 0x36, 0xac, 0x92, + 0xb0, 0x23, 0x26, 0xfa, 0xd8, 0xa3, 0xe8, 0x84, + 0xfc, 0x52, 0xc5, 0x7b, 0xd1, 0x4b, 0xe2, 0x1a, + 0x33, 0xdd, 0x3c, 0xdf, 0x27, 0x50, 0x6f, 0x12, + 0xd3, 0x17, 0x66, 0xd7, 0x54, 0x33, 0x30, 0x2b, + 0xe8, 0xd1, 0x1f, 0x2d, 0xf3, 0x37, 0x81, 0xa0, + 0x3c, 0x21, 0x8c, 0xea, 0x95, 0xa5, 0x5b, 0x3a, + 0x24, 0xed, 0xf7, 0x67, 0x7b, 0x72, 0x3a, 0xda, + 0x31, 0xbd, 0xa7, 0x63, 0xa6, 0x6f, 0xf9, 0xdf, + 0x06, 0x36, 0xb4, 0xe2, 0x35, 0x4b, 0xa5, 0x8e, + 0x29, 0x8e, 0x6c, 0x02, 0xc5, 0x06, 0x9b, 0x98, + 0x6e, 0x5e, 0x00, 0x6a, 0x42, 0x09, 0x4b, 0xc3, + 0x09, 0x37, 0x67, 0x19, 0x58, 0x6d, 0x40, 0x50, + 0xb0, 0x62, 0x5b, 0xd6, 0x63, 0x7f, 0xed, 0xb0, + 0x97, 0x80, 0x9e, 0x91, 0x3f, 0x82, 0xfd, 0x83, + 0x36, 0xce, 0x06, 0xc4, 0xdc, 0xa4, 0x1e, 0x70, + 0xd4, 0x94, 0xfc, 0x6e, 0x46, 0xa3, 0xc8, 0xed, + 0x34, 0x0a, 0xb1, 0x9a, 0x66, 0x5d, 0xc0, 0xce, + 0x73, 0xd3, 0x65, 0xcb, 0xfb, 0x79, 0xdd, 0xf6, + 0x19, 0xf6, 0xd8, 0xa9, 0xe6, 0x34, 0x15, 0x86, + 0x7a, 0x30, 0x79, 0xde, 0x2b, 0x06, 0xa4, 0xc0, + 0xc8, 0xa2, 0xc1, 0x41, 0xb3, 0x4c, 0xf6, 0xdb, + 0x16, 0xcd, 0xd2, 0x8b, 0xf1, 0x18, 0x5a, 0xc8, + 0x3e, 0xd9, 0x54, 0x40, 0xd4, 0xce, 0x88, 0xbb, + 0x66, 0xf1, 0x74, 0x20, 0xa2, 0x3c, 0x31, 0x09, + 0xba, 0xac, 0x61, 0x15, 0x9f, 0x73, 0x5f, 0xa7, + 0xe5, 0x0d, 0xb3, 0xab, 0xa2, 0x72, 0x25, 0xc9, + 0x87, 0x9b, 0x18, 0xdb, 0xff, 0xfb, 0x39, 0x84, + 0x8d, 0xf8, 0x97, 0x47, 0xab, 0xc4, 0xfb, 0xc2, + 0xd8, 0xe8, 0xce, 0x6e, 0x65, 0x76, 0x88, 0x4a, + 0x22, 0x2f, 0xdd, 0x43, 0xa7, 0xc4, 0x8d, 0x32, + 0x12, 0x75, 0x0b, 0x72, 0xd6, 0xb7, 0x43, 0x84, + 0xc8, 0x59, 0xa8, 0xb7, 0x8b, 0x84, 0x33, 0x92, + 0x8f, 0x94, 0xe8, 0xd0, 0xaf, 0x11, 0x35, 0xde, + 0xb7, 0x63, 0xb8, 0x91, 0x4c, 0x96, 0x4e, 0x9c, + 0x62, 0x28, 0xa2, 0xbc, 0x0b, 0x90, 0xae, 0x94, + 0x90, 0xe9, 0x32, 0xeb, 0xe3, 0x77, 0x60, 0x5f, + 0x87, 0x48, 0x4b, 0xb0, 0x78, 0x0e, 0xe2, 0x85, + 0x47, 0x06, 0xa4, 0xc9, 0x26, 0xac, 0x8f, 0xe7, + 0xc2, 0xc7, 0xce, 0xf5, 0xd1, 0x20, 0xa8, 0x56, + 0xe1, 0x4f, 0x50, 0x90, 0xb3, 0xc1, 0x03, 0x57, + 0xd3, 0x62, 0x0e, 0x2a, 0xe8, 0x86, 0xf4, 0x94, + 0x0e, 0xa5, 0x8b, 0x4e, 0x73, 0xa2, 0x76, 0xac, + 0x00, 0x29, 0xe5, 0x80, 0x26, 0x02, 0x13, 0xd1, + 0xb2, 0x68, 0x72, 0x23, 0x38, 0x55, 0xfc, 0x4d, + 0x05, 0x60, 0x49, 0x7b, 0xfb, 0xaa, 0x17, 0x8f, + 0x26, 0x0a, 0x08, 0x33, 0x8d, 0x7f, 0x4e, 0xe5, + 0x6e, 0xf8, 0x84, 0x9b, 0x9f, 0xcb, 0xa2, 0x2b, + 0xfb, 0xaf, 0xad, 0x21, 0xe2, 0x4f, 0x6f, 0x55, + 0xc1, 0x78, 0x46, 0xe3, 0xb5, 0x63, 0x06, 0x9b, + 0x93, 0x7d, 0xac, 0xd4, 0xe0, 0x64, 0x01, 0x8d, + 0xac, 0x30, 0x8b, 0x8b, 0x55, 0xb7, 0x8a, 0x16, + 0x3f, 0xc9, 0x82, 0x7f, 0xb5, 0x3b, 0x0d, 0xc0, + 0x46, 0x89, 0x5c, 0x6c, 0x45, 0x21, 0x78, 0xda, + 0x84, 0x1f, 0xc8, 0xcf, 0xf1, 0x1e, 0x79, 0x71, + 0x3b, 0xc8, 0xe2, 0x8b, 0x41, 0xfe, 0xaf, 0x2f, + 0x3b, 0x23, 0x13, 0xc5, 0x46, 0x87, 0xc6, 0x24, + 0x37, 0x21, 0x68, 0x8a, 0x3e, 0x45, 0x61, 0xf4, + 0xad, 0xf5, 0x1c, 0x23, 0x45, 0xa3, 0x42, 0xf2, + 0xa9, 0xac, 0x94, 0x50, 0xc9, 0x3d, 0x5e, 0x70, + 0x33, 0x2b, 0x78, 0xd1, 0x5c, 0x13, 0x35, 0xe6, + 0x13, 0x80, 0x5e, 0x55, 0xa7, 0xcc, 0x67, 0xb0, + 0x6c, 0xfe, 0xa2, 0x24, 0x02, 0x6d, 0xb3, 0xcb, + 0x9e, 0x94, 0xb3, 0xc6, 0x01, 0xf3, 0x01, 0x3a, + 0xe4, 0xa7, 0xa3, 0xdf, 0x56, 0x4c, 0x30, 0xce, + 0xb1, 0xd5, 0x1b, 0x68, 0x9b, 0x75, 0xae, 0xf4, + 0xb9, 0x2a, 0xe5, 0x8b, 0x7b, 0xe5, 0x99, 0x46, + 0x5f, 0x29, 0xf6, 0x82, 0xd0, 0x42, 0xb1, 0x45, + 0x09, 0x16, 0x5b, 0x32, 0x11, 0xca, 0x48, 0xea, + 0x51, 0x12, 0x0a, 0x9f, 0x6e, 0x3f, 0x74, 0xe6, + 0xe0, 0xfe, 0xf8, 0xa5, 0xc0, 0xfd, 0x15, 0x6e, + 0x2b, 0x4a, 0xd5, 0x76, 0xa8, 0x3d, 0xe3, 0x0d, + 0xfe, 0x44, 0x11, 0x5e, 0x7a, 0xde, 0x12, 0x29, + 0x5a, 0x5a, 0x25, 0xc0, 0x8e, 0x98, 0xd1, 0x11, + 0xc8, 0x00, 0x65, 0xb2, 0xf4, 0xd7, 0x56, 0x32, + 0x46, 0x2b, 0x4f, 0x7e, 0xc3, 0x4e, 0xf1, 0x17, + 0xff, 0x03, 0x32, 0xae, 0xe3, 0xbe, 0x0b, 0xab, + 0xfb, 0x43, 0x0f, 0x6d, 0xa5, 0xc6, 0x44, 0xba, + 0xc9, 0xe3, 0x3d, 0x40, 0xe7, 0x6c, 0xe8, 0x21, + 0xb2, 0x46, 0x7b, 0x3b, 0x3d, 0xde, 0x80, 0xc8, + 0xea, 0xf4, 0x6b, 0xf3, 0x53, 0xca, 0x51, 0x84, + 0xcf, 0xad, 0x7e, 0xce, 0xce, 0xc2, 0x65, 0xfc, + 0x03, 0x8c, 0xcb, 0xfa, 0xcb, 0x37, 0x89, 0x82, + 0x59, 0x5e, 0x36, 0x52, 0xe4, 0xbc, 0x8d, 0x47, + 0x7c, 0xb8, 0x3f, 0x63, 0x59, 0xdc, 0xd3, 0x74, + 0x11, 0x33, 0xb4, 0x69, 0x74, 0x40, 0x0d, 0x42, + 0x63, 0x1d, 0xe6, 0x5c, 0x1b, 0xca, 0x41, 0xff, + 0x23, 0x4e, 0xe8, 0x3d, 0x14, 0xa8, 0x17, 0x18, + 0xd0, 0x78, 0x08, 0x87, 0x7d, 0x5e, 0xdc, 0x3a, + 0x07, 0xba, 0x12, 0x8e, 0x8e, 0x56, 0x0a, 0xcb, + 0x37, 0xf6, 0x54, 0xeb, 0x55, 0x16, 0x8f, 0x06, + 0x15, 0x28, 0x6b, 0xfb, 0xed, 0x38, 0x9e, 0x9b, + 0x98, 0x5b, 0xdc, 0x67, 0x33, 0x0e, 0x02, 0x36, + 0x1b, 0x7a, 0x9a, 0x43, 0xcd, 0xf2, 0x65, 0xef, + 0x37, 0x19, 0x24, 0x6f, 0x4b, 0xb9, 0x4d, 0x3e, + 0x0b, 0x47, 0xd1, 0x67, 0x50, 0x6a, 0x7f, 0x07 +#elif !defined(WOLFSSL_NO_ML_DSA_65) + 0x30, 0x82, 0x07, 0xb4, 0x30, 0x0d, 0x06, 0x0b, + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0b, + 0x0c, 0x06, 0x05, 0x03, 0x82, 0x07, 0xa1, 0x00, + 0xff, 0x89, 0xee, 0xad, 0x20, 0x8f, 0x61, 0xa4, + 0x07, 0x1c, 0x54, 0x98, 0x8c, 0xf4, 0x2e, 0xd9, + 0xe6, 0x0f, 0xcb, 0x0e, 0xab, 0xa1, 0x37, 0x4d, + 0xc0, 0x48, 0x24, 0x78, 0xd6, 0x2d, 0x9b, 0x6f, + 0x0f, 0x17, 0x08, 0x71, 0xc3, 0xd1, 0xc8, 0x7a, + 0xe7, 0x32, 0xcb, 0xcd, 0xd6, 0xb5, 0x90, 0x08, + 0xe1, 0xda, 0xaa, 0x89, 0x3e, 0x4a, 0x62, 0x98, + 0x3d, 0xc6, 0x71, 0x30, 0xb4, 0x63, 0xa5, 0x3b, + 0xb3, 0x69, 0x75, 0x10, 0xaf, 0x5e, 0x72, 0x78, + 0xa2, 0xef, 0x63, 0x63, 0x21, 0xe7, 0xf4, 0xa7, + 0x9c, 0x50, 0x74, 0x14, 0x3e, 0xdd, 0x73, 0x9e, + 0x97, 0x65, 0xdd, 0xdf, 0x3c, 0x40, 0x4d, 0x03, + 0x49, 0xe4, 0xbf, 0x65, 0xe7, 0x44, 0x8f, 0x59, + 0x00, 0xe2, 0x98, 0xb5, 0x66, 0xa3, 0x3b, 0x11, + 0x9f, 0xc7, 0xc2, 0x16, 0x61, 0xf0, 0x1e, 0x89, + 0xc8, 0x96, 0x8d, 0x18, 0xac, 0x86, 0xa0, 0xe2, + 0xd9, 0x8c, 0xef, 0x53, 0x6d, 0x4e, 0x74, 0xc9, + 0x66, 0x28, 0x16, 0xf3, 0x62, 0xc4, 0x6f, 0x2b, + 0x6e, 0x36, 0x03, 0xad, 0xc5, 0xe4, 0x8f, 0x0b, + 0x90, 0x8c, 0x8f, 0xff, 0x5d, 0xdf, 0x7a, 0xe6, + 0xaf, 0x9a, 0x43, 0xbc, 0xd4, 0x73, 0x22, 0xdc, + 0x5f, 0x08, 0xa1, 0x17, 0x97, 0x89, 0x79, 0xf5, + 0xdc, 0xed, 0x4f, 0x85, 0x8e, 0x0c, 0x23, 0x35, + 0x3c, 0x34, 0x19, 0x65, 0xf5, 0xd6, 0xc9, 0x2d, + 0x7a, 0x2e, 0x67, 0xd5, 0xf1, 0x82, 0x97, 0xaa, + 0x05, 0x26, 0x84, 0x25, 0x47, 0x58, 0x2c, 0xe6, + 0x59, 0xc7, 0x98, 0x7a, 0xdb, 0x40, 0x45, 0x1c, + 0x71, 0x55, 0x2e, 0xea, 0x3f, 0x6e, 0x7c, 0x82, + 0x52, 0x6a, 0x19, 0x3a, 0xd3, 0xa1, 0x3c, 0xce, + 0x00, 0x06, 0xec, 0xed, 0x97, 0xce, 0xd8, 0xdf, + 0xde, 0xa3, 0xed, 0xe7, 0x81, 0x62, 0x02, 0x9c, + 0x1b, 0x51, 0xa1, 0xf4, 0x9d, 0x1b, 0x28, 0x76, + 0x93, 0x96, 0x20, 0x55, 0x60, 0x1f, 0xaf, 0x52, + 0xc3, 0xce, 0xb9, 0x12, 0x66, 0xf5, 0x64, 0x22, + 0x87, 0x86, 0x29, 0x80, 0x8f, 0x18, 0x33, 0xba, + 0x48, 0x71, 0x1d, 0x00, 0xfe, 0xa5, 0xfc, 0xc6, + 0x87, 0xbe, 0x44, 0x3c, 0xc9, 0x49, 0xfb, 0x68, + 0x3c, 0xdf, 0xca, 0xef, 0xa7, 0xdc, 0x67, 0xb8, + 0x28, 0xd6, 0xad, 0x18, 0xaf, 0xad, 0x1f, 0x4c, + 0x85, 0xa3, 0x64, 0xac, 0x3f, 0xa9, 0x39, 0x28, + 0xef, 0x8a, 0x45, 0x7e, 0xb0, 0xf4, 0x89, 0x72, + 0xf7, 0xb1, 0xef, 0x9d, 0x1c, 0x3c, 0x93, 0xcb, + 0xa0, 0xfb, 0x2a, 0x90, 0xe2, 0x1d, 0x49, 0x8e, + 0x36, 0xb8, 0x07, 0xf4, 0xb3, 0x09, 0xf0, 0x6f, + 0x3c, 0xd9, 0x37, 0x19, 0x57, 0xd4, 0x1e, 0x2a, + 0xa2, 0xa7, 0x2e, 0xc1, 0xcd, 0x8d, 0x48, 0x47, + 0xb5, 0x8a, 0x12, 0x93, 0x34, 0xb8, 0xec, 0x32, + 0x07, 0x49, 0xb6, 0x8d, 0x73, 0xd4, 0x2c, 0x6a, + 0xa0, 0x33, 0x29, 0x21, 0x5d, 0x37, 0xa9, 0x39, + 0x40, 0xbe, 0x71, 0x29, 0xbe, 0xd1, 0x4b, 0xbc, + 0x9a, 0x17, 0x93, 0x52, 0xb8, 0x81, 0xee, 0xc5, + 0xff, 0x25, 0x78, 0x2f, 0x52, 0x0a, 0x8f, 0xb2, + 0xef, 0xf3, 0x1d, 0x68, 0x56, 0x31, 0x29, 0x84, + 0x55, 0x47, 0x32, 0x34, 0x0f, 0x60, 0x07, 0xd6, + 0x2b, 0xb9, 0x29, 0xaf, 0x0f, 0xcd, 0x1c, 0xc0, + 0x77, 0x4c, 0xc6, 0x31, 0xdb, 0xf4, 0x17, 0xbe, + 0x3d, 0xf8, 0x8c, 0xf1, 0x02, 0x7c, 0x6b, 0xd4, + 0xaf, 0x03, 0xb2, 0xf4, 0x78, 0x8d, 0xd3, 0x4e, + 0x5c, 0x04, 0xb9, 0x01, 0xe3, 0x73, 0xb4, 0x67, + 0xe9, 0xa8, 0x77, 0x6f, 0x87, 0x2b, 0xe2, 0x00, + 0x98, 0x5f, 0x02, 0x43, 0x85, 0x03, 0x4c, 0x71, + 0xd2, 0xe7, 0x61, 0x03, 0x22, 0x9e, 0xe5, 0xc2, + 0xa7, 0x66, 0x42, 0x7c, 0x9f, 0xf4, 0xb8, 0x6b, + 0x2d, 0xe4, 0xaa, 0x51, 0xda, 0x08, 0x73, 0x75, + 0x26, 0x45, 0xdc, 0xa6, 0x20, 0xd7, 0xcb, 0x00, + 0xfc, 0xe4, 0xdb, 0x28, 0x92, 0xf8, 0xb0, 0xc7, + 0xf0, 0x4b, 0x6d, 0xe8, 0xc1, 0x84, 0x38, 0xed, + 0x1a, 0xd4, 0x66, 0x69, 0xc4, 0x96, 0x40, 0xc4, + 0x7d, 0xfa, 0x58, 0x70, 0x7e, 0x70, 0x40, 0xba, + 0xfc, 0x95, 0xb6, 0x4c, 0x7c, 0x58, 0xbc, 0xb3, + 0x59, 0x08, 0x14, 0x03, 0x35, 0xf3, 0xf1, 0xaa, + 0xd5, 0xa2, 0x57, 0x70, 0xb6, 0x20, 0x75, 0x0a, + 0x58, 0x66, 0x74, 0xf7, 0x1c, 0xfd, 0x99, 0x7c, + 0x20, 0xda, 0xe7, 0x76, 0xcb, 0xf4, 0xa3, 0x9b, + 0xbc, 0x8f, 0x74, 0xef, 0xe2, 0x46, 0x5a, 0x72, + 0x33, 0x06, 0x32, 0x1e, 0xbd, 0x4e, 0x4c, 0xf6, + 0x16, 0x43, 0xa5, 0xa5, 0xa5, 0x6c, 0x76, 0x33, + 0x35, 0x63, 0xdc, 0xe4, 0xec, 0x7f, 0x8a, 0xfa, + 0xc3, 0x53, 0x69, 0x28, 0xf7, 0xd6, 0x97, 0xb9, + 0x3a, 0xf4, 0x15, 0x90, 0x50, 0xd3, 0xdf, 0xf5, + 0xd3, 0xcf, 0x15, 0x76, 0xe3, 0x3d, 0x24, 0x14, + 0xfd, 0xd3, 0x01, 0x25, 0x82, 0xb4, 0xe3, 0xd8, + 0x68, 0x89, 0x86, 0xa8, 0x26, 0x02, 0x5f, 0xc6, + 0xf4, 0x99, 0x3b, 0x97, 0xa8, 0x65, 0xed, 0x18, + 0xbb, 0x3c, 0x43, 0x4a, 0x6e, 0xaa, 0xbc, 0x83, + 0x85, 0x19, 0x9f, 0x9b, 0xb8, 0xa4, 0xa3, 0xb2, + 0xb7, 0x56, 0x07, 0x6c, 0xbf, 0x7d, 0xff, 0x5d, + 0xb5, 0x1e, 0x83, 0xc8, 0x74, 0x70, 0x98, 0x17, + 0x40, 0xe0, 0x2d, 0xad, 0x31, 0x00, 0x8e, 0x42, + 0xd5, 0xb2, 0x25, 0xaa, 0x82, 0xaf, 0x33, 0xd8, + 0x5b, 0xe2, 0x07, 0xed, 0xda, 0x84, 0xe9, 0xa2, + 0xff, 0xbb, 0xa5, 0x47, 0x95, 0x6e, 0xa1, 0x8d, + 0x59, 0x52, 0xeb, 0xf3, 0x3c, 0x18, 0x29, 0x92, + 0x72, 0x27, 0x18, 0xfc, 0x95, 0xb9, 0xde, 0x46, + 0xda, 0xcc, 0x4c, 0x31, 0x1d, 0x78, 0x86, 0xd2, + 0x8c, 0x38, 0x9c, 0x32, 0xab, 0xf7, 0xca, 0x73, + 0x85, 0xa5, 0xf1, 0xe0, 0x25, 0x06, 0xf9, 0x18, + 0x14, 0xab, 0x3b, 0x73, 0x26, 0xee, 0xa0, 0xfd, + 0x15, 0xac, 0xd6, 0x4e, 0x6b, 0xdb, 0x01, 0xa1, + 0xdc, 0xd1, 0x2f, 0xd2, 0xb7, 0x5e, 0x12, 0x4f, + 0x4b, 0x59, 0xd8, 0x03, 0x12, 0x60, 0xc9, 0x81, + 0xb7, 0x06, 0x23, 0x09, 0xc4, 0xd9, 0xa8, 0x93, + 0x6e, 0x96, 0xf4, 0x93, 0x53, 0xf0, 0x3d, 0xde, + 0x10, 0x88, 0xb1, 0xd0, 0xcc, 0xad, 0x2c, 0xbf, + 0x88, 0x98, 0x8f, 0x25, 0x76, 0xd7, 0x65, 0x77, + 0xcc, 0x36, 0x1d, 0x1b, 0x6b, 0x60, 0x58, 0xc4, + 0xfe, 0xe6, 0xca, 0xa8, 0x29, 0x33, 0x69, 0x36, + 0xb8, 0x12, 0x95, 0x38, 0xd9, 0xd4, 0x16, 0xe9, + 0x3e, 0x40, 0x8c, 0xc7, 0xae, 0x04, 0x11, 0xdf, + 0x51, 0xd3, 0xdd, 0xbf, 0xa9, 0x41, 0x43, 0x4c, + 0xff, 0x87, 0x2f, 0xea, 0x0f, 0x13, 0x66, 0x2a, + 0x2b, 0x18, 0xe8, 0xc4, 0xff, 0xa0, 0x1c, 0x78, + 0x79, 0x21, 0xf8, 0xaa, 0x8a, 0xf8, 0x92, 0xdf, + 0x7b, 0x5f, 0x6a, 0x71, 0x60, 0x67, 0x5d, 0x94, + 0xf6, 0xbb, 0x1d, 0x90, 0x7c, 0x51, 0x70, 0x1d, + 0x87, 0xde, 0xf8, 0x91, 0xcb, 0x42, 0x9f, 0xc7, + 0x4b, 0xa0, 0x16, 0xee, 0xb4, 0x73, 0xe8, 0xe0, + 0x0b, 0xa5, 0xd3, 0x26, 0x9e, 0x52, 0xda, 0x4a, + 0x1f, 0xae, 0x76, 0xbf, 0xbb, 0x4d, 0x74, 0x98, + 0xa6, 0xae, 0xc0, 0x60, 0x96, 0xc5, 0xad, 0x9b, + 0x91, 0x31, 0xb9, 0x50, 0x3d, 0x9a, 0x0f, 0xe1, + 0x93, 0xef, 0x08, 0x72, 0xb2, 0x66, 0xe5, 0x5d, + 0xe4, 0x15, 0x53, 0x8e, 0xb0, 0xb3, 0xf8, 0x78, + 0xfc, 0x5d, 0x44, 0xc5, 0xbf, 0xf5, 0x01, 0x54, + 0xc5, 0x45, 0xa9, 0x30, 0xa4, 0xf1, 0x49, 0x79, + 0x4e, 0xab, 0xfc, 0xb2, 0x93, 0xe7, 0x3a, 0xe1, + 0x7f, 0x1f, 0x2f, 0x45, 0x3a, 0x53, 0x2b, 0x68, + 0xb3, 0xa4, 0xac, 0x23, 0x54, 0xb7, 0x5d, 0x25, + 0xa3, 0xe3, 0x90, 0x8a, 0xb0, 0x02, 0xfb, 0x7f, + 0x2d, 0xeb, 0x80, 0xc2, 0x5c, 0x62, 0xe1, 0x36, + 0x5a, 0x82, 0x8f, 0x4e, 0x74, 0xeb, 0x7d, 0x70, + 0xaf, 0x23, 0x92, 0x65, 0x3a, 0x11, 0xc0, 0x29, + 0xdb, 0xf7, 0x9a, 0xdc, 0x81, 0x45, 0x25, 0x0c, + 0x2e, 0x4f, 0x88, 0x41, 0x34, 0x53, 0xc6, 0x08, + 0x21, 0x77, 0xc1, 0xbb, 0x61, 0x48, 0x20, 0x69, + 0x1a, 0xbb, 0x71, 0x1b, 0x56, 0x18, 0x79, 0x75, + 0x16, 0x9a, 0xb3, 0x79, 0x31, 0x11, 0xa2, 0x89, + 0x8d, 0xea, 0x10, 0xb0, 0x04, 0x7f, 0xf8, 0x6e, + 0xdc, 0x08, 0x9b, 0x51, 0xa7, 0x64, 0xbd, 0x8d, + 0xd4, 0xd0, 0x1e, 0x38, 0x50, 0x1a, 0xa8, 0x7e, + 0x20, 0xae, 0xee, 0x8c, 0xa7, 0x72, 0x94, 0xc9, + 0xba, 0xf0, 0x67, 0xbd, 0x25, 0x1a, 0x3a, 0xdf, + 0x75, 0x39, 0xb7, 0xd3, 0x83, 0x3b, 0x89, 0xdf, + 0xb5, 0x2d, 0xd3, 0x12, 0x24, 0x21, 0x7c, 0x9e, + 0x92, 0x1c, 0x19, 0xae, 0x28, 0xcb, 0x2e, 0x2e, + 0x3c, 0xa9, 0x9b, 0xbd, 0xf9, 0x33, 0x30, 0xb2, + 0xbd, 0x8b, 0xbf, 0xc1, 0x8b, 0x32, 0xf1, 0x20, + 0xa1, 0x00, 0xfd, 0x11, 0x7d, 0x9a, 0xa8, 0x14, + 0x2c, 0xce, 0x16, 0x16, 0x4b, 0xdd, 0x56, 0x91, + 0x15, 0x36, 0x83, 0xcb, 0x01, 0x58, 0x35, 0xe1, + 0xdc, 0x22, 0x3d, 0xf8, 0xc2, 0x06, 0x54, 0x68, + 0x77, 0xd1, 0x47, 0x28, 0xdc, 0x09, 0x2a, 0x86, + 0x13, 0x80, 0xa6, 0xe9, 0xd0, 0xb4, 0xa3, 0x41, + 0x47, 0xf4, 0x71, 0x24, 0x10, 0x4c, 0x9f, 0xb7, + 0x57, 0x34, 0x48, 0x1b, 0xb4, 0xed, 0x0e, 0x89, + 0x4c, 0xf1, 0x73, 0x44, 0xff, 0x35, 0xb6, 0xe0, + 0x8f, 0x02, 0xa3, 0xa3, 0x81, 0x55, 0x38, 0xb5, + 0xc1, 0x99, 0xb3, 0x88, 0x84, 0x0d, 0xd9, 0x73, + 0x77, 0x65, 0x0b, 0xd7, 0xf8, 0x03, 0x88, 0xcb, + 0xdf, 0x25, 0xaf, 0xc6, 0xf1, 0xfa, 0x5c, 0x4d, + 0xfa, 0xc3, 0x7b, 0x8f, 0xb8, 0x38, 0x5d, 0x29, + 0xbb, 0x3d, 0x3e, 0x62, 0x1c, 0xdd, 0xe6, 0x97, + 0xe6, 0xe9, 0xbe, 0x6e, 0xd2, 0xb7, 0x7a, 0x9a, + 0x8e, 0xaf, 0xb3, 0xc8, 0x9e, 0x19, 0xee, 0x3d, + 0x5b, 0x1f, 0xec, 0x34, 0x3a, 0x1c, 0x27, 0x90, + 0xbd, 0x1e, 0x49, 0x72, 0x25, 0x2e, 0x38, 0x48, + 0x7d, 0xe1, 0x85, 0x46, 0xa7, 0x1b, 0x4a, 0xd5, + 0x23, 0x75, 0x6d, 0x8b, 0xc3, 0xf1, 0x87, 0xec, + 0x8b, 0x45, 0xf0, 0x9b, 0xb2, 0x14, 0x7a, 0x7c, + 0x8d, 0x78, 0x9c, 0x82, 0x64, 0x14, 0xfe, 0x01, + 0xfa, 0x04, 0x33, 0x96, 0xdd, 0x5f, 0x56, 0xbc, + 0xb2, 0x03, 0xe3, 0x0c, 0xa1, 0x09, 0x66, 0xa0, + 0x5e, 0x44, 0xde, 0x21, 0xae, 0x7d, 0x7a, 0x0e, + 0x81, 0x27, 0xd2, 0xfb, 0x85, 0xed, 0x27, 0x27, + 0xac, 0x11, 0x1c, 0xa1, 0x6d, 0xe9, 0xc1, 0xca, + 0xf6, 0x40, 0x7c, 0x95, 0x01, 0xb7, 0xa8, 0x29, + 0x9a, 0xd2, 0xcc, 0x62, 0x70, 0x1c, 0x7d, 0x0e, + 0xe5, 0x60, 0xcb, 0x79, 0xa3, 0xd7, 0x5d, 0x48, + 0x4b, 0x3c, 0xf8, 0x12, 0xe8, 0x7a, 0x7e, 0x83, + 0xab, 0x24, 0x33, 0x0f, 0x7b, 0x0a, 0x38, 0xae, + 0xb1, 0xfc, 0xc3, 0x50, 0x5c, 0x83, 0x53, 0xfd, + 0x15, 0xd6, 0x49, 0x54, 0xb6, 0x40, 0xe5, 0xe8, + 0x55, 0xba, 0x08, 0x2f, 0x21, 0xd7, 0x0e, 0x71, + 0x8a, 0xb2, 0xe1, 0x6b, 0xc6, 0x7e, 0x0f, 0x1c, + 0x4d, 0x41, 0x9f, 0x38, 0xc2, 0xce, 0x41, 0x41, + 0x48, 0xcd, 0xec, 0x16, 0x1d, 0x23, 0x8e, 0x41, + 0xcd, 0x5e, 0xf9, 0x5f, 0x01, 0x5e, 0x73, 0xa2, + 0xa1, 0xef, 0xe9, 0x57, 0xe0, 0xba, 0xe6, 0xbb, + 0x2b, 0xff, 0x3e, 0xb8, 0xad, 0xd5, 0x12, 0xc1, + 0x54, 0x49, 0xca, 0x93, 0xb0, 0x7d, 0x7b, 0xcf, + 0xf0, 0xc5, 0x94, 0x43, 0x30, 0x94, 0x11, 0x8d, + 0x15, 0x79, 0x2e, 0x57, 0xb8, 0x24, 0xcd, 0x2e, + 0xc2, 0x49, 0x3d, 0x92, 0x44, 0x23, 0x0c, 0x3e, + 0xa0, 0xf9, 0xa5, 0xad, 0x2a, 0x56, 0xec, 0xf4, + 0x6d, 0x0f, 0x5b, 0xb5, 0xd4, 0x2a, 0x3f, 0x2b, + 0x17, 0x9f, 0x5d, 0x33, 0x97, 0x42, 0xd4, 0x1e, + 0x14, 0x49, 0x01, 0xfb, 0xb6, 0x72, 0xbc, 0x14, + 0x5b, 0x79, 0xf4, 0x0a, 0xc5, 0x49, 0xe1, 0x76, + 0x44, 0x78, 0x87, 0xd1, 0x8e, 0x5b, 0xd5, 0x95, + 0xad, 0x19, 0x7c, 0x0d, 0x39, 0x7f, 0x41, 0x2e, + 0xd7, 0x9e, 0xbc, 0xfd, 0x2c, 0xde, 0xfa, 0x01, + 0x7d, 0x2b, 0x04, 0xef, 0x4d, 0xf9, 0xf4, 0x5b, + 0xed, 0x05, 0x9a, 0x50, 0x35, 0xe7, 0xb0, 0xba, + 0x24, 0xea, 0x16, 0x51, 0xe1, 0x6f, 0x32, 0x08, + 0x94, 0xd6, 0x19, 0x9d, 0x0e, 0x4c, 0xc1, 0xbb, + 0x01, 0x87, 0xa5, 0x90, 0x5f, 0x6f, 0xc4, 0xed, + 0xa1, 0x4c, 0x06, 0x4d, 0x2c, 0x47, 0x24, 0xda, + 0xae, 0xd2, 0x41, 0x92, 0x1f, 0x46, 0xce, 0xec, + 0xb1, 0xcc, 0x80, 0x1e, 0xb2, 0xcb, 0x66, 0x48, + 0x22, 0xec, 0x0e, 0x47, 0xfc, 0xad, 0x17, 0xfe, + 0x7b, 0xc5, 0x4d, 0x34, 0x95, 0x40, 0xd0, 0x02, + 0x7e, 0x90, 0xaa, 0x92, 0xaf, 0x48, 0x64, 0xc5, + 0xc1, 0x56, 0xd8, 0x9b, 0x6c, 0x5f, 0x2e, 0xfa, + 0xd7, 0x84, 0xdc, 0x71, 0x65, 0x1b, 0xfb, 0xbc, + 0x21, 0xc7, 0x57, 0xf4, 0x71, 0x2e, 0x6f, 0x34, + 0x85, 0x99, 0xa8, 0x5c, 0x6f, 0x34, 0x22, 0x44, + 0x89, 0x01, 0xf9, 0x48, 0xd2, 0xe2, 0xe4, 0x71, + 0x9d, 0x48, 0x07, 0x97, 0xd4, 0x66, 0xe4, 0x4d, + 0x48, 0xa3, 0x08, 0x7f, 0x6e, 0xaa, 0x7b, 0xe9, + 0x93, 0x81, 0x03, 0x0c, 0xd2, 0x48, 0xcf, 0x3f, + 0x5f, 0xbe, 0x03, 0xfb, 0x0f, 0xad, 0xc3, 0x81, + 0xd9, 0xce, 0x88, 0x0b, 0xfa, 0xed, 0x29, 0x7e, + 0x0b, 0xa1, 0x6f, 0x4c, 0x7d, 0xe4, 0x36, 0xff, + 0xdf, 0x94, 0x1a, 0x24, 0xb3, 0x7b, 0xca, 0x24, + 0x7e, 0x3a, 0x19, 0x53, 0x13, 0x4a, 0x17, 0x58, + 0xe7, 0x16, 0x9b, 0x50, 0xd8, 0xda, 0xcc, 0x6e, + 0x05, 0x25, 0xfe, 0x16, 0xcb, 0x5b, 0xd5, 0x35, + 0x76, 0x40, 0x44, 0x96, 0x23, 0x97, 0xe2, 0x4a, + 0x72, 0x0c, 0x54, 0x43, 0xc0, 0x09, 0x85, 0x8e, + 0x15, 0x85, 0xaf, 0x3c, 0x5e, 0x5f, 0x3c, 0x2d, + 0x21, 0x42, 0x75, 0xb7, 0xe4, 0x50, 0xf9, 0x00, + 0xa3, 0x4f, 0xb1, 0x7c, 0xfe, 0x62, 0xd0, 0xe9, + 0x6d, 0x51, 0xcc, 0x83, 0xc1, 0xdc, 0x37, 0x10, + 0x90, 0x0a, 0x15, 0xd8, 0xd5, 0x02, 0xf7, 0x74, + 0xb8, 0x46, 0x84, 0xc3, 0x61, 0x17, 0x26, 0x0f, + 0xe4, 0xde, 0x1a, 0xcf, 0x42, 0x53, 0x63, 0x2f, + 0x8d, 0xf7, 0x06, 0x07, 0xc3, 0x33, 0x39, 0x59, + 0xe9, 0x17, 0xc8, 0x05, 0xd2, 0xa2, 0xae, 0x53, + 0x2c, 0x7e, 0xd0, 0x9d, 0x5c, 0xb5, 0x42, 0x9f, + 0x84, 0xd7, 0xfe, 0x93, 0x74, 0xfb, 0xbb, 0xd2, + 0x1e, 0x57, 0x4e, 0x7f, 0x79, 0xaf, 0xd2, 0xf9, + 0x5e, 0x41, 0x9e, 0x63, 0x54, 0x61, 0x47, 0x0c, + 0x92, 0x4c, 0xc9, 0xfe, 0x4f, 0xcb, 0xe5, 0x8e, + 0x65, 0xb3, 0x97, 0x1b, 0xd8, 0xd1, 0x62, 0xfd +#else + 0x30, 0x82, 0x0a, 0x34, 0x30, 0x0d, 0x06, 0x0b, + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0b, + 0x0c, 0x08, 0x07, 0x03, 0x82, 0x0a, 0x21, 0x00, + 0x7f, 0x5f, 0x63, 0x81, 0x6f, 0x04, 0x4c, 0xec, + 0xa8, 0xaf, 0x7b, 0x99, 0x41, 0xc6, 0xff, 0xdf, + 0x77, 0x66, 0x28, 0xc0, 0xe2, 0x58, 0xea, 0x9c, + 0x60, 0xbb, 0x03, 0x3e, 0xca, 0xa8, 0x38, 0x64, + 0xfb, 0xf7, 0x1b, 0x3f, 0xec, 0xfd, 0x0f, 0xf1, + 0x9c, 0xe4, 0xfd, 0xad, 0x83, 0xf7, 0x03, 0x66, + 0x6e, 0x7f, 0x4d, 0x42, 0xab, 0x6b, 0x73, 0x26, + 0xde, 0x6f, 0x8c, 0xc4, 0xca, 0x21, 0x66, 0x31, + 0x79, 0x57, 0x88, 0xcb, 0x1e, 0xab, 0xda, 0x1d, + 0x56, 0x70, 0xd9, 0x83, 0xa1, 0xb4, 0x83, 0xce, + 0xcc, 0x0f, 0xeb, 0xd6, 0x63, 0xbd, 0xf6, 0x02, + 0x5d, 0x5b, 0x0c, 0x17, 0x3c, 0x3e, 0x15, 0x02, + 0x22, 0xa1, 0x5d, 0xb5, 0xc5, 0x81, 0x28, 0x95, + 0x0b, 0x34, 0x2b, 0x96, 0x0a, 0xae, 0x6a, 0xa8, + 0xb5, 0x1d, 0x56, 0xbb, 0x7d, 0x83, 0x9a, 0x15, + 0xad, 0x63, 0x9e, 0x86, 0x8c, 0x6e, 0x6a, 0xa8, + 0xde, 0x55, 0xd0, 0xce, 0xc0, 0x2e, 0x05, 0xfe, + 0x1f, 0x4d, 0xd7, 0x12, 0xa4, 0x5a, 0xe9, 0x04, + 0x0d, 0x20, 0x84, 0x90, 0xb9, 0xca, 0x64, 0xe4, + 0xad, 0x2e, 0x74, 0x4b, 0x1d, 0x2f, 0xcc, 0xac, + 0xd8, 0x1a, 0x5e, 0xb2, 0x78, 0xbe, 0x61, 0xf7, + 0x36, 0xa3, 0xd1, 0x93, 0x86, 0xb5, 0x15, 0xf1, + 0x74, 0xf8, 0x9f, 0x6d, 0x6a, 0x8f, 0x6d, 0x86, + 0x8b, 0x36, 0x61, 0x10, 0xc9, 0x1a, 0x31, 0x39, + 0x09, 0xe6, 0x15, 0xa0, 0xb1, 0xfa, 0x69, 0xd4, + 0xc2, 0xb2, 0x56, 0x4c, 0x06, 0x33, 0x13, 0xc4, + 0x78, 0x53, 0x16, 0xfc, 0x52, 0x99, 0xe6, 0x27, + 0xc9, 0x3b, 0x24, 0x5c, 0x3e, 0x85, 0x73, 0x76, + 0x61, 0xa3, 0x61, 0xf0, 0x95, 0xd5, 0xb2, 0xf5, + 0x21, 0xe7, 0x09, 0xc3, 0x0c, 0x5c, 0xb0, 0x36, + 0xce, 0x45, 0x68, 0x41, 0x45, 0xcb, 0x1c, 0x36, + 0x2f, 0x3a, 0x00, 0x07, 0x56, 0xbe, 0x61, 0xd2, + 0x77, 0x37, 0x63, 0xa4, 0xdb, 0xfa, 0xa9, 0x6b, + 0x37, 0x90, 0x35, 0xd1, 0x1e, 0x27, 0x5b, 0x3e, + 0xc0, 0x0a, 0x02, 0x64, 0xe4, 0x58, 0x49, 0xab, + 0x2d, 0xc1, 0x38, 0x29, 0x3d, 0x44, 0xf9, 0xac, + 0xb7, 0x65, 0xd1, 0x5f, 0xf8, 0xce, 0x52, 0x76, + 0x22, 0x15, 0x61, 0x02, 0x1f, 0xa7, 0xcd, 0xff, + 0xeb, 0xa6, 0x7f, 0x6b, 0xba, 0x75, 0xe3, 0x09, + 0x01, 0x06, 0x41, 0x20, 0x88, 0x75, 0x64, 0x6b, + 0x97, 0x38, 0x13, 0xab, 0x4c, 0x0a, 0xd4, 0x7e, + 0xd2, 0xfa, 0x78, 0xe8, 0x9f, 0x5d, 0xf9, 0x53, + 0x30, 0x17, 0xf1, 0x10, 0x9e, 0x4a, 0x32, 0x17, + 0x3a, 0x9b, 0xb9, 0x25, 0x8e, 0xeb, 0xd9, 0x41, + 0x01, 0xa2, 0xc6, 0x58, 0x4a, 0x9f, 0xc3, 0x73, + 0xfd, 0xe2, 0xe4, 0x2c, 0x92, 0xb4, 0xa2, 0x3d, + 0x0f, 0x1f, 0x37, 0x64, 0xf1, 0x17, 0x2a, 0x8c, + 0xc6, 0xb5, 0xb0, 0x69, 0x7d, 0xfe, 0x08, 0xe0, + 0x8e, 0xaa, 0xe0, 0x08, 0xd5, 0x28, 0x92, 0x51, + 0x73, 0x8a, 0x2f, 0x7a, 0x4a, 0xbf, 0x52, 0x8d, + 0x3e, 0x9b, 0x36, 0x6a, 0xfb, 0x19, 0xf0, 0xea, + 0xfe, 0x05, 0xbd, 0x2d, 0xa9, 0x58, 0x48, 0x02, + 0xa8, 0x20, 0x9e, 0xdc, 0x04, 0x57, 0xc2, 0x0c, + 0xae, 0xc1, 0x03, 0xe7, 0x17, 0x48, 0x80, 0x00, + 0x8d, 0x1b, 0xd0, 0xc5, 0xdc, 0x2a, 0x02, 0x6e, + 0x8e, 0x54, 0xf3, 0x79, 0x31, 0x02, 0x93, 0xc5, + 0xf2, 0x55, 0xea, 0x61, 0xd0, 0xb2, 0x8e, 0xc9, + 0x74, 0x17, 0x0d, 0x38, 0xf8, 0xab, 0xf4, 0x42, + 0xd4, 0xc2, 0xdc, 0xf7, 0x1b, 0xdb, 0x65, 0x36, + 0x9f, 0x56, 0xe2, 0xeb, 0xf7, 0xe5, 0x2d, 0x45, + 0xae, 0xc0, 0x95, 0xbc, 0xe4, 0x1f, 0x22, 0xdc, + 0x0f, 0x54, 0xed, 0x14, 0xb8, 0xf1, 0x2f, 0x5d, + 0xd1, 0x79, 0xa0, 0x81, 0x17, 0x71, 0xa1, 0xd6, + 0xf0, 0x88, 0x9c, 0x1c, 0xc7, 0x95, 0x07, 0xb0, + 0xea, 0xf7, 0xd3, 0xa2, 0x55, 0xfe, 0x85, 0x65, + 0x42, 0x06, 0xec, 0xd2, 0xbe, 0x03, 0x8f, 0x63, + 0x84, 0x4b, 0xb1, 0x47, 0x48, 0x20, 0x71, 0xd2, + 0xdf, 0xc9, 0x59, 0xb0, 0x24, 0x8a, 0x6e, 0xf9, + 0x4a, 0xa1, 0x7b, 0xed, 0x11, 0xb6, 0xf9, 0x9b, + 0xf7, 0x93, 0x0e, 0xcb, 0x7a, 0x32, 0x22, 0x23, + 0x4e, 0x86, 0xce, 0xad, 0x9d, 0x1b, 0x84, 0x57, + 0xaf, 0xa5, 0x04, 0x03, 0x0a, 0xc9, 0x04, 0x97, + 0xd0, 0xce, 0x8e, 0x2a, 0x9a, 0x00, 0x15, 0xeb, + 0xac, 0x96, 0x57, 0xde, 0xe6, 0xc1, 0x2d, 0xbd, + 0xfc, 0xd6, 0x95, 0x0f, 0x5f, 0x19, 0xac, 0xaf, + 0x6c, 0xd8, 0xa6, 0x1e, 0xd8, 0xdb, 0x14, 0xfd, + 0xba, 0x0f, 0xd0, 0x3f, 0x61, 0xe3, 0x76, 0xfc, + 0x47, 0x61, 0x07, 0x24, 0x49, 0x17, 0xca, 0x24, + 0x31, 0x16, 0x26, 0x4f, 0xdc, 0x2b, 0x39, 0xae, + 0x5f, 0xfa, 0x4f, 0x82, 0xef, 0xe1, 0x41, 0x8c, + 0x3e, 0x8e, 0xa7, 0x6c, 0xf2, 0x51, 0xf7, 0x85, + 0x35, 0x6c, 0xad, 0xea, 0x32, 0x35, 0xf3, 0xc0, + 0x14, 0x17, 0xe2, 0x98, 0x27, 0x36, 0x7e, 0x60, + 0x2f, 0x01, 0x60, 0x3e, 0x18, 0xf4, 0x4e, 0xe0, + 0xf5, 0x14, 0x21, 0x81, 0x05, 0x78, 0x1c, 0x5f, + 0x4e, 0x89, 0xbb, 0x23, 0x60, 0xb1, 0x8f, 0x07, + 0x53, 0x16, 0x6e, 0xfb, 0x86, 0x07, 0x90, 0xff, + 0xa6, 0x27, 0x60, 0xe6, 0x3e, 0x92, 0x2a, 0x3c, + 0xa3, 0x57, 0xec, 0x97, 0x23, 0xaf, 0xd2, 0x44, + 0xac, 0x09, 0x87, 0xb0, 0x54, 0xe9, 0x5b, 0x50, + 0x37, 0xfa, 0x12, 0xa4, 0xcb, 0x6f, 0xed, 0x9f, + 0x29, 0x73, 0xa7, 0x09, 0x29, 0x91, 0x93, 0x5c, + 0x54, 0xf4, 0x44, 0xc2, 0x04, 0x64, 0xfc, 0xd2, + 0xf2, 0x0a, 0x0b, 0x45, 0x1f, 0xc5, 0x18, 0xf0, + 0xff, 0x10, 0x1f, 0x3a, 0x97, 0xf8, 0xb1, 0x83, + 0x0e, 0x08, 0xe2, 0x55, 0x75, 0x6a, 0x45, 0x96, + 0xf8, 0x1b, 0xdc, 0xb6, 0x57, 0x83, 0x8c, 0x28, + 0xc0, 0x4a, 0x57, 0xc6, 0xfb, 0x27, 0x3d, 0xfa, + 0x5a, 0x0d, 0x69, 0x56, 0x23, 0x66, 0x02, 0x78, + 0xca, 0xf1, 0xfa, 0xcb, 0xc1, 0xf6, 0x92, 0x1c, + 0xa0, 0xe3, 0x09, 0x7d, 0x48, 0x5e, 0x86, 0xa0, + 0x82, 0xa8, 0xf1, 0x1e, 0xe1, 0xfe, 0xc6, 0x9d, + 0x4f, 0x2e, 0xf4, 0xfc, 0xc6, 0x48, 0x1d, 0xc1, + 0x2a, 0x6a, 0xb7, 0xea, 0x46, 0x89, 0x04, 0xe9, + 0xbd, 0xf1, 0xed, 0x16, 0x76, 0xd8, 0x4b, 0x42, + 0xd5, 0x43, 0xa4, 0xfb, 0x02, 0x01, 0x54, 0x00, + 0xaf, 0x55, 0x52, 0x27, 0xff, 0x00, 0xe2, 0xbb, + 0x4a, 0xf2, 0x69, 0xb4, 0x4e, 0x6c, 0x6b, 0xa3, + 0x96, 0x4f, 0xf4, 0x65, 0x90, 0x2d, 0xc8, 0x57, + 0x1f, 0xb2, 0xf0, 0x86, 0x7b, 0x93, 0x09, 0x49, + 0x31, 0xc4, 0xf4, 0x8f, 0xc8, 0x2d, 0xac, 0x1d, + 0xfc, 0xba, 0xa4, 0xa5, 0x41, 0x90, 0x76, 0x7d, + 0x9e, 0x47, 0xdc, 0x10, 0xe6, 0x0c, 0xf7, 0x0f, + 0xa4, 0xba, 0x4f, 0xe2, 0x46, 0x38, 0x4c, 0x28, + 0xa0, 0x57, 0xb5, 0x3c, 0xb3, 0x4b, 0x8f, 0x03, + 0x04, 0xff, 0xf6, 0xec, 0x60, 0x90, 0x62, 0xfe, + 0x74, 0x76, 0x48, 0xb3, 0xf4, 0x0a, 0x6a, 0x5a, + 0x5b, 0xad, 0xc8, 0x54, 0x62, 0x11, 0x52, 0xd9, + 0x84, 0x1a, 0x09, 0x4b, 0xca, 0x66, 0xaa, 0x3c, + 0x36, 0x08, 0x9d, 0x58, 0xd0, 0x4a, 0x3a, 0x8b, + 0x24, 0xe0, 0x80, 0x9f, 0xe3, 0x76, 0xb6, 0x07, + 0xb1, 0xbc, 0x00, 0x98, 0xb0, 0xc1, 0xe0, 0xf6, + 0x1f, 0x4d, 0xa8, 0xd1, 0x69, 0x44, 0x9c, 0x33, + 0xb0, 0x0f, 0x9c, 0xc9, 0x0c, 0x8c, 0xbc, 0x03, + 0x58, 0x81, 0x76, 0xab, 0x0d, 0xef, 0x25, 0x5a, + 0xf6, 0xab, 0x3b, 0xf1, 0x1f, 0x97, 0x12, 0x8e, + 0x7f, 0x28, 0x77, 0x26, 0x18, 0xc4, 0xc4, 0xda, + 0x2c, 0x43, 0x57, 0xd2, 0x1f, 0x67, 0x95, 0x40, + 0x2c, 0x94, 0x41, 0x69, 0x22, 0x8a, 0x24, 0xd9, + 0xc7, 0xfc, 0xea, 0x49, 0x83, 0x8f, 0x5d, 0x2e, + 0x9d, 0xac, 0x17, 0xb6, 0xe0, 0xc4, 0xe7, 0xe6, + 0xd5, 0xc2, 0x73, 0xa1, 0x8f, 0x33, 0x14, 0x02, + 0xae, 0x01, 0x9f, 0x6f, 0x40, 0x92, 0x4e, 0x03, + 0xc2, 0xa9, 0xf1, 0x36, 0x78, 0xe4, 0xde, 0x39, + 0x4d, 0x29, 0x2e, 0xc2, 0x00, 0x93, 0x79, 0xe4, + 0xb2, 0x29, 0x4b, 0x81, 0x5c, 0x06, 0x06, 0xbc, + 0xc1, 0x01, 0x1c, 0xa7, 0x08, 0xf7, 0x47, 0x1f, + 0x52, 0x4f, 0xdf, 0x94, 0x1e, 0xe6, 0x89, 0xe6, + 0x26, 0x71, 0x2e, 0xa2, 0xd2, 0xfe, 0x04, 0xf2, + 0x12, 0x4c, 0x06, 0x78, 0x34, 0xc0, 0xb9, 0x76, + 0x62, 0x3b, 0x72, 0x25, 0x8c, 0x0d, 0x73, 0x24, + 0xcf, 0x4b, 0x4c, 0x47, 0x20, 0x9d, 0x04, 0x7f, + 0x86, 0x2c, 0x45, 0xb8, 0xfe, 0xb2, 0xaa, 0x36, + 0xf8, 0xe0, 0x24, 0x25, 0x05, 0x23, 0x12, 0x16, + 0xbf, 0x64, 0x10, 0xdd, 0xe4, 0xc0, 0xb0, 0x85, + 0xa7, 0xd3, 0xd1, 0x18, 0x1b, 0x81, 0x6b, 0x94, + 0xfd, 0x07, 0x43, 0xdd, 0x12, 0x37, 0x78, 0x69, + 0xec, 0x8c, 0xd0, 0x41, 0x2c, 0x42, 0x94, 0x3e, + 0x9f, 0xe3, 0x49, 0xb3, 0xb8, 0x45, 0x0b, 0x1d, + 0xc1, 0x9b, 0x4d, 0x21, 0x85, 0x62, 0xea, 0xd1, + 0xc9, 0x12, 0x30, 0x8c, 0x4b, 0x63, 0xeb, 0x7d, + 0x02, 0x52, 0x15, 0xa1, 0x95, 0x48, 0x9f, 0xc2, + 0xce, 0xf3, 0x4b, 0xff, 0x5a, 0xb6, 0x8f, 0xce, + 0xcd, 0x42, 0x21, 0x40, 0x82, 0xad, 0x08, 0x99, + 0x4d, 0x24, 0x58, 0x25, 0xf3, 0x7e, 0x42, 0x86, + 0x06, 0x33, 0x1f, 0x53, 0xbb, 0x07, 0x33, 0xca, + 0xc0, 0x02, 0x18, 0x30, 0x3c, 0xc5, 0x67, 0x1c, + 0x32, 0x3f, 0x2d, 0x58, 0x4c, 0x24, 0x6e, 0x60, + 0x96, 0x1a, 0xf4, 0xd0, 0x55, 0xb8, 0x84, 0xf0, + 0xb9, 0x83, 0xbf, 0x3d, 0x37, 0xe4, 0xa6, 0x06, + 0x1c, 0xd1, 0xd7, 0x91, 0x24, 0xdc, 0x3f, 0xcc, + 0x71, 0xf3, 0x0c, 0x90, 0x2c, 0x1d, 0x2f, 0x90, + 0xc8, 0x3c, 0x6f, 0x2c, 0x5d, 0xad, 0x8c, 0xdf, + 0xbb, 0x0d, 0x2a, 0x7f, 0x4a, 0x34, 0x5a, 0xd9, + 0x83, 0xfd, 0x61, 0x36, 0xe0, 0x0a, 0xb3, 0xf6, + 0x69, 0xb1, 0xaf, 0x81, 0x22, 0xd6, 0x9e, 0x9a, + 0xf8, 0xa6, 0x24, 0x8e, 0x0c, 0xcb, 0x25, 0xc2, + 0xfc, 0xc5, 0x94, 0xbd, 0x23, 0x9c, 0xa9, 0xbd, + 0x76, 0x28, 0xa4, 0x55, 0x92, 0x7c, 0xe6, 0x76, + 0xf7, 0x30, 0xf8, 0x7d, 0xdc, 0x0a, 0x93, 0x9e, + 0x7c, 0x39, 0x0a, 0x70, 0xa0, 0xb2, 0x77, 0xe0, + 0x7a, 0x89, 0x50, 0xce, 0x75, 0xca, 0x2f, 0xa4, + 0x12, 0x0e, 0xcb, 0x75, 0x1f, 0x0a, 0x83, 0xe8, + 0x14, 0x80, 0xa7, 0xb0, 0xe8, 0x11, 0xca, 0x12, + 0x5e, 0xf7, 0x31, 0x65, 0xbd, 0x20, 0x3d, 0x8c, + 0xa6, 0x89, 0x83, 0x68, 0x66, 0x03, 0x28, 0x49, + 0x17, 0xc4, 0x3f, 0x43, 0x02, 0x9b, 0xf8, 0xed, + 0xae, 0x8e, 0x68, 0xbc, 0x8e, 0x39, 0xe7, 0x15, + 0x32, 0x45, 0x66, 0x2c, 0x1f, 0xce, 0x56, 0xc7, + 0xc0, 0x15, 0x52, 0x19, 0x40, 0xcf, 0x87, 0x20, + 0xcd, 0x3d, 0xec, 0x90, 0x8d, 0x04, 0x01, 0x31, + 0x0b, 0x74, 0x80, 0x6e, 0x61, 0xa7, 0xf3, 0x4c, + 0xb2, 0x16, 0x00, 0xd5, 0xdb, 0xcc, 0xbb, 0x2c, + 0x9f, 0xb6, 0x02, 0x4a, 0xcf, 0x71, 0x06, 0xfd, + 0x60, 0xe0, 0x00, 0xbe, 0x22, 0xba, 0x39, 0x36, + 0xa8, 0x7e, 0xe5, 0xcb, 0xea, 0x87, 0xb1, 0xee, + 0xa2, 0x6c, 0x85, 0x94, 0x18, 0x6c, 0xab, 0x9a, + 0x93, 0xa7, 0xab, 0x4e, 0x3b, 0x85, 0xf3, 0xef, + 0x8f, 0x15, 0x74, 0x21, 0x9f, 0x5d, 0x9c, 0x22, + 0x32, 0x71, 0xb5, 0x4d, 0x7f, 0xaa, 0x85, 0xe0, + 0x05, 0x2a, 0x53, 0xbb, 0x3c, 0xab, 0xc3, 0xd2, + 0x73, 0x6e, 0x97, 0xa3, 0xfd, 0x05, 0x58, 0xaa, + 0x49, 0xc8, 0x69, 0xa9, 0x0b, 0x73, 0xd4, 0xe9, + 0x1d, 0x84, 0x60, 0x34, 0x2a, 0x09, 0xb3, 0x0f, + 0x08, 0x13, 0x67, 0x77, 0xb3, 0x24, 0xdf, 0xad, + 0xbf, 0x51, 0x71, 0x2b, 0xbe, 0x4f, 0x5d, 0xf4, + 0xe7, 0x25, 0x4c, 0x24, 0xa2, 0x4a, 0x22, 0xec, + 0xcc, 0x7c, 0x6c, 0x62, 0xee, 0x47, 0x12, 0x43, + 0x88, 0xe4, 0x71, 0xaa, 0x63, 0xaa, 0x2b, 0xed, + 0x70, 0xbf, 0x26, 0x37, 0xcc, 0xa4, 0xff, 0xe9, + 0xb6, 0x65, 0x31, 0x4d, 0x0d, 0x32, 0xd6, 0x84, + 0xb8, 0xab, 0x98, 0xa7, 0x10, 0x44, 0x77, 0xc7, + 0x2a, 0x60, 0xf0, 0xf5, 0xd5, 0xd4, 0x3a, 0x73, + 0x11, 0xa5, 0x1b, 0x18, 0x3c, 0x13, 0xfb, 0xda, + 0x76, 0x9d, 0xeb, 0x3e, 0xb9, 0x7a, 0xce, 0x02, + 0xa7, 0x5e, 0x25, 0x96, 0xd2, 0xbc, 0x85, 0x1a, + 0xd1, 0xa4, 0xe2, 0x02, 0x15, 0x08, 0x49, 0x16, + 0x7c, 0xaf, 0xc6, 0x38, 0x7b, 0x95, 0xf9, 0x37, + 0xc0, 0x87, 0x73, 0x6f, 0x01, 0xcd, 0x2b, 0xf1, + 0xe7, 0x6e, 0x47, 0x18, 0x30, 0xb8, 0x16, 0x87, + 0x1d, 0x23, 0x62, 0x22, 0x85, 0x92, 0x69, 0x46, + 0x9c, 0x65, 0xd8, 0xf1, 0x27, 0x32, 0xe4, 0x16, + 0x7f, 0x9a, 0xba, 0x46, 0x61, 0x60, 0x34, 0xe5, + 0xc0, 0x14, 0xb5, 0xde, 0x4d, 0xd1, 0x71, 0x39, + 0x26, 0xdc, 0x0c, 0x0a, 0x53, 0x9e, 0x31, 0x10, + 0x45, 0x7a, 0xf9, 0xc8, 0xfa, 0x1d, 0x69, 0x5e, + 0x25, 0xc1, 0xe2, 0x00, 0xbf, 0x94, 0xa3, 0xa2, + 0x97, 0xca, 0xb4, 0x6a, 0x89, 0x68, 0xdd, 0xed, + 0x6b, 0x99, 0x5a, 0x87, 0x9e, 0xe9, 0x68, 0xe4, + 0xf2, 0xc2, 0x7e, 0x37, 0x02, 0xdf, 0x96, 0x1a, + 0x5b, 0xed, 0xa1, 0xe8, 0xdf, 0x3c, 0xf7, 0xd2, + 0x25, 0xac, 0xf7, 0x4a, 0x7f, 0x10, 0x27, 0x2b, + 0x02, 0xc7, 0x95, 0x10, 0x5a, 0xb5, 0xb0, 0xcd, + 0xa9, 0xe1, 0x36, 0xe2, 0x1c, 0x87, 0x99, 0x0e, + 0x0a, 0x44, 0xec, 0x97, 0x75, 0xa7, 0x03, 0x27, + 0x38, 0x3b, 0x16, 0x30, 0x00, 0x98, 0xbe, 0x77, + 0xfe, 0x3a, 0xac, 0x6f, 0x8f, 0x4d, 0xe1, 0xa9, + 0x9c, 0xba, 0x39, 0x52, 0xe8, 0xf7, 0xe4, 0xe6, + 0xf9, 0xe9, 0xb3, 0x57, 0x82, 0xb2, 0x23, 0xd6, + 0xa5, 0x14, 0xc0, 0x78, 0xb4, 0xa0, 0xf9, 0x96, + 0xe4, 0x03, 0xe8, 0x6c, 0x27, 0xd8, 0x37, 0x7c, + 0x8f, 0xf4, 0x80, 0x09, 0x09, 0xc9, 0x32, 0x15, + 0xe0, 0x3f, 0x37, 0xa7, 0x1a, 0x5f, 0x8c, 0xfb, + 0xdd, 0xfe, 0x6b, 0x34, 0x28, 0x53, 0x03, 0x4b, + 0x39, 0x91, 0xf2, 0x48, 0x4c, 0x2a, 0x45, 0xfe, + 0x66, 0xf7, 0x23, 0x74, 0xb8, 0x30, 0x70, 0xb4, + 0x0c, 0x2c, 0x65, 0xb1, 0x4e, 0x32, 0x0f, 0x50, + 0xbb, 0x46, 0x9b, 0x03, 0x34, 0x38, 0xfb, 0xe4, + 0x25, 0x37, 0x8d, 0x0f, 0xa1, 0x41, 0x50, 0x85, + 0x92, 0x07, 0x71, 0xff, 0x3c, 0xe6, 0xd9, 0x1d, + 0x55, 0xb7, 0x10, 0x9c, 0xea, 0x70, 0x5f, 0xa3, + 0xba, 0x84, 0x99, 0x91, 0x30, 0x3d, 0x4c, 0x98, + 0x0b, 0x1f, 0x1f, 0xcc, 0x17, 0x94, 0xdd, 0x78, + 0x7d, 0x50, 0xe5, 0xf5, 0x21, 0x88, 0x5a, 0x52, + 0x76, 0x5a, 0x97, 0xbe, 0xba, 0xa9, 0xfe, 0x82, + 0x8a, 0xb5, 0x46, 0xcf, 0x9c, 0xbe, 0xe8, 0x2f, + 0x01, 0x2f, 0x6a, 0x03, 0x8a, 0xfa, 0x4b, 0x0b, + 0xdc, 0x78, 0x79, 0x9c, 0x49, 0xc4, 0x01, 0x26, + 0x16, 0x58, 0xc6, 0xb8, 0xee, 0x6c, 0xc9, 0xa9, + 0x38, 0x7c, 0xcf, 0xf3, 0xf8, 0xd0, 0x6b, 0x99, + 0x43, 0x13, 0xe0, 0x43, 0x8e, 0xfb, 0xb2, 0xdb, + 0x61, 0x67, 0xf4, 0xfc, 0x01, 0x21, 0xd9, 0xb1, + 0x1e, 0x6c, 0x6f, 0x2a, 0x9a, 0x4b, 0x86, 0x3c, + 0x62, 0x03, 0x53, 0x83, 0x11, 0x18, 0x1a, 0x59, + 0x9e, 0x25, 0xfe, 0xdb, 0x85, 0xd0, 0xee, 0x7c, + 0x97, 0x72, 0xca, 0xf3, 0x0d, 0xd4, 0x19, 0x66, + 0x14, 0xaf, 0x46, 0x68, 0x75, 0xdb, 0x8f, 0x5f, + 0x77, 0x7f, 0xfe, 0xa9, 0xe6, 0xa1, 0x9e, 0x46, + 0x5e, 0x92, 0xda, 0xea, 0xdd, 0x89, 0x01, 0xd9, + 0xab, 0x25, 0x7d, 0xb4, 0x64, 0x50, 0x8f, 0xa3, + 0xbe, 0xe2, 0x03, 0xd5, 0xc6, 0x9c, 0xc2, 0xf8, + 0xac, 0xa4, 0x36, 0xa9, 0x37, 0x10, 0x59, 0x00, + 0x45, 0xbb, 0x55, 0x33, 0xb9, 0x6f, 0xbc, 0xa2, + 0x02, 0x9e, 0xa3, 0x1d, 0xf4, 0x17, 0x78, 0x9b, + 0xbc, 0x42, 0x4e, 0x21, 0xc3, 0xde, 0xb5, 0x70, + 0x4a, 0x23, 0x1e, 0xd4, 0x36, 0x5d, 0x7a, 0x08, + 0x37, 0x55, 0x98, 0x07, 0xa0, 0x16, 0xa3, 0x4e, + 0xa1, 0x2b, 0x96, 0x8b, 0x51, 0x63, 0x48, 0xab, + 0xc9, 0x19, 0x6f, 0x5f, 0x25, 0x9d, 0xe7, 0x25, + 0x63, 0xf0, 0x8e, 0xdb, 0x06, 0x2d, 0x42, 0x31, + 0xfd, 0x14, 0x2b, 0x7a, 0x31, 0x43, 0x04, 0xd5, + 0xe2, 0x89, 0x2e, 0xa8, 0xe4, 0x6e, 0xd5, 0xa5, + 0x21, 0x67, 0x9b, 0x92, 0x61, 0x79, 0xdd, 0xe5, + 0x44, 0x43, 0x45, 0x57, 0x13, 0xec, 0x04, 0xc1, + 0x41, 0xa3, 0x14, 0x70, 0x86, 0xda, 0x76, 0x5d, + 0xe8, 0x61, 0xd2, 0xfb, 0x7b, 0xe4, 0x71, 0x46, + 0xa3, 0x52, 0xbf, 0xf2, 0xa0, 0x3c, 0xc1, 0x90, + 0x0c, 0x2e, 0xeb, 0xb3, 0x38, 0xae, 0x13, 0x27, + 0x84, 0xe9, 0x7a, 0xd6, 0x02, 0x40, 0x84, 0xff, + 0x87, 0x1f, 0x37, 0x44, 0xd8, 0x2e, 0x93, 0xf7, + 0x0a, 0xff, 0x5b, 0x4d, 0x07, 0x82, 0xfd, 0x6e, + 0x44, 0xcc, 0x19, 0xc3, 0x7d, 0x7c, 0x31, 0xf9, + 0x0e, 0xa8, 0x1c, 0x0d, 0xcb, 0x8e, 0xe8, 0x33, + 0xb2, 0xff, 0x9e, 0x1d, 0x99, 0x7c, 0x46, 0x5b, + 0xc7, 0x28, 0xec, 0x01, 0x62, 0x82, 0xfe, 0x2a, + 0x22, 0xa3, 0x86, 0x4e, 0x47, 0xe2, 0x57, 0xf1, + 0xb4, 0x58, 0x94, 0x89, 0xe5, 0xf1, 0xcd, 0x4d, + 0x90, 0xd1, 0xa4, 0x4c, 0x34, 0x5d, 0xde, 0xdc, + 0x39, 0x63, 0x8b, 0x85, 0xfd, 0x02, 0x21, 0xf1, + 0x12, 0xa3, 0x6d, 0x65, 0x0f, 0x8d, 0xe5, 0xcd, + 0x70, 0xd5, 0x1d, 0xf8, 0x65, 0x99, 0xfb, 0xe8, + 0xb5, 0x5a, 0x09, 0x39, 0x9e, 0x09, 0x45, 0x62, + 0x22, 0x1d, 0xa2, 0x46, 0xbf, 0x75, 0x20, 0xd1, + 0xe7, 0xb0, 0x06, 0x68, 0xc3, 0x50, 0x48, 0xfc, + 0xf8, 0x5c, 0x67, 0x69, 0x68, 0x66, 0xb6, 0x81, + 0x95, 0x91, 0x81, 0x3d, 0xf6, 0x34, 0xd9, 0x4b, + 0x06, 0x35, 0x17, 0x59, 0x89, 0x18, 0x74, 0x32, + 0x50, 0xcf, 0x81, 0x16, 0x8e, 0x53, 0x9d, 0x1c, + 0xad, 0x2d, 0x8e, 0x16, 0x41, 0xda, 0xca, 0xab, + 0x78, 0x0d, 0xc9, 0x49, 0x61, 0xaa, 0x18, 0xf4, + 0x56, 0x48, 0x29, 0x8c, 0xe3, 0x9a, 0x7d, 0x58, + 0xf8, 0x99, 0x72, 0xf1, 0x78, 0xa8, 0x5a, 0x97, + 0xe3, 0x2a, 0xc6, 0xa9, 0x59, 0xde, 0xcc, 0x62, + 0xfb, 0xab, 0xc5, 0x9a, 0x0b, 0xc7, 0x16, 0x8f, + 0x18, 0x20, 0x6e, 0x01, 0x7e, 0x04, 0xef, 0x72, + 0x83, 0x61, 0xb8, 0x1a, 0x77, 0x0f, 0xd1, 0xa9, + 0x75, 0xe0, 0x4a, 0x11, 0x69, 0x9d, 0xb6, 0xc9, + 0x2e, 0xd3, 0xbf, 0xe2, 0x5b, 0x24, 0x77, 0x30, + 0x85, 0x91, 0xef, 0xa8, 0x93, 0x4e, 0xad, 0x99, + 0xad, 0xcb, 0x6d, 0x9d, 0x8f, 0xd8, 0x0f, 0xe5, + 0x41, 0xd9, 0x9e, 0x0b, 0xce, 0x33, 0xd9, 0xbb, + 0x87, 0x66, 0x2c, 0xa3, 0x0b, 0x68, 0x1b, 0xb0, + 0x71, 0x30, 0xfa, 0x15, 0x2e, 0xe8, 0xc1, 0x99, + 0x71, 0x01, 0xcc, 0xdb, 0x6f, 0x9f, 0x8a, 0xfd, + 0xb4, 0x0f, 0x35, 0xa1, 0x36, 0xf4, 0x3a, 0xc4, + 0x17, 0x77, 0x43, 0x60, 0x10, 0x18, 0xb4, 0xc2, + 0xe5, 0xc0, 0x64, 0xd8, 0x38, 0x7c, 0x05, 0x9a, + 0xfb, 0x2b, 0xb3, 0x9b, 0x9e, 0x34, 0x6b, 0x4b, + 0xc8, 0x3b, 0x77, 0xe0, 0x6f, 0x08, 0xa1, 0x7b, + 0x66, 0x69, 0x2f, 0xdb, 0x34, 0x9e, 0x98, 0x90, + 0x5b, 0x4d, 0x7b, 0xa2, 0x32, 0x8e, 0x64, 0xe6, + 0x0d, 0x75, 0xc9, 0x96, 0xe3, 0x57, 0xba, 0xad, + 0x3e, 0x3b, 0x23, 0xfb, 0x9e, 0x7f, 0xc0, 0x3c, + 0xd5, 0x41, 0x9c, 0xfb, 0xbc, 0xb3, 0x52, 0x49 +#endif +}; +#endif + +static int test_wc_dilithium_public_der_decode(void) +{ + EXPECT_DECLS; +#if defined(HAVE_DILITHIUM) && defined(WOLFSSL_WC_DILITHIUM) && \ + defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) + dilithium_key* key; + word32 idx = 0; + + key = (dilithium_key*)XMALLOC(sizeof(*key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + ExpectNotNull(key); + + if (key != NULL) { + XMEMSET(key, 0, sizeof(*key)); + } + + ExpectIntEQ(wc_dilithium_init(key), 0); +#ifndef WOLFSSL_NO_ML_DSA_44 + ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_44), 0); +#elif !defined(WOLFSSL_NO_ML_DSA_65) + ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_65), 0); +#else + ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_87), 0); +#endif + ExpectIntEQ(wc_Dilithium_PublicKeyDecode(dilithium_public_der, &idx, key, + (word32)sizeof(dilithium_public_der)), 0); + + wc_dilithium_free(key); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return EXPECT_RESULT(); +} + static int test_wc_dilithium_der(void) { EXPECT_DECLS; @@ -32276,6 +33059,15 @@ static int test_wc_dilithium_der(void) ExpectIntEQ(len = wc_Dilithium_PublicKeyToDer(key, der, DILITHIUM_MAX_DER_SIZE, 1), pubDerLen); idx = 0; +{ + fprintf(stderr, "\n"); + for (int ii = 0; ii < pubDerLen; ii++) { + if ((ii % 8) == 0) fprintf(stderr, " "); + fprintf(stderr, "0x%02x,", der[ii]); + if ((ii % 8) == 7) fprintf(stderr, "\n"); + else fprintf(stderr, " "); + } +} ExpectIntEQ(wc_Dilithium_PublicKeyDecode(der, &idx, key, len), 0); ExpectIntEQ(len = wc_Dilithium_PrivateKeyToDer(key, der, @@ -83230,6 +84022,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_wc_dilithium_sign), TEST_DECL(test_wc_dilithium_verify), TEST_DECL(test_wc_dilithium_check_key), + TEST_DECL(test_wc_dilithium_public_der_decode), TEST_DECL(test_wc_dilithium_der), TEST_DECL(test_wc_dilithium_make_key_from_seed), TEST_DECL(test_wc_dilithium_verify_kats), diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index 8af0a920b..521353c60 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -58,6 +58,19 @@ * WOLFSSL_DILITHIUM_SIGN_SMALL_MEM Default: OFF * Compiles signature implementation that uses smaller amounts of memory but * is considerably slower. + * WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC Default: OFF + * Compiles signature implementation that uses smaller amounts of memory but + * is considerably slower. Allocates vectors and decodes private key data + * into them upfront. + * WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A Default: OFF + * Compiles signature implementation that uses smaller amounts of memory but + * is slower. Allocates matrix A and calculates it upfront. + * WOLFSSL_DILITHIUM_MAKE_KEY_SMALL_MEM Default: OFF + * Compiles key generation implementation that uses smaller amounts of memory + * but is slower. + * WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 Default: OFF + * Compiles the small memory implementations to use a 64-bit polynomial. + * Uses 2KB of memory but is slighlty quicker (2.75-7%). * * WOLFSSL_DILITHIUM_ALIGNMENT Default: 8 * Use to indicate whether loading and storing of words needs to be aligned. @@ -142,6 +155,18 @@ #include #endif +#if defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM) + #define WOLFSSL_DILITHIUM_SIGN_SMALL_MEM +#endif +#if defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM) + #define WOLFSSL_DILITHIUM_SIGN_SMALL_MEM + #ifdef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC + #error "PRECALC and PRECALC_A is equivalent to non small mem" + #endif +#endif + #ifdef WOLFSSL_WC_DILITHIUM #ifdef DEBUG_DILITHIUM @@ -1678,43 +1703,24 @@ static void dilithium_vec_encode_w1(const sword32* w1, byte k, sword32 gamma2, * @param [in, out] shake128 SHAKE-128 object. * @param [in] seed Seed to hash to generate values. * @param [out] a Polynomial. + * @param [in] h Buffer to hold hashes. * @return 0 on success. - * @return MEMORY_E when dynamic memory allocation fails. * @return Negative on hash error. */ -static int dilithium_rej_ntt_poly(wc_Shake* shake128, byte* seed, sword32* a, - byte* key_h) +static int dilithium_rej_ntt_poly_ex(wc_Shake* shake128, byte* seed, sword32* a, + byte* h) { -#ifdef WOLFSSL_DILITHIUM_SMALL int ret = 0; +#ifdef WOLFSSL_DILITHIUM_SMALL int j = 0; -#if defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) - byte* h = NULL; -#else - byte h[DILITHIUM_REJ_NTT_POLY_H_SIZE]; + +#if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* Reading 4 bytes for 3 so need to set 1 past for last read. */ + h[DILITHIUM_GEN_A_BLOCK_BYTES] = 0; #endif - (void)key_h; - -#ifdef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC - h = key_h; -#elif defined(WOLFSSL_SMALL_STACK) - h = (byte*)XMALLOC(DILITHIUM_REJ_NTT_POLY_H_SIZE, NULL, - DYNAMIC_TYPE_DILITHIUM); - if (h == NULL) { - ret = MEMORY_E; - } -#endif /* WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC */ - - if (ret == 0) { - #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) - /* Reading 4 bytes for 3 so need to set 1 past for last read. */ - h[DILITHIUM_GEN_A_BLOCK_BYTES] = 0; - #endif - - /* Initialize SHAKE-128 object for new hash. */ - ret = wc_InitShake128(shake128, NULL, INVALID_DEVID); - } + /* Initialize SHAKE-128 object for new hash. */ + ret = wc_InitShake128(shake128, NULL, INVALID_DEVID); if (ret == 0) { /* Absorb the seed. */ ret = wc_Shake128_Absorb(shake128, seed, DILITHIUM_GEN_A_SEED_SZ); @@ -1750,39 +1756,14 @@ static int dilithium_rej_ntt_poly(wc_Shake* shake128, byte* seed, sword32* a, } } } - -#if !defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) && defined(WOLFSSL_SMALL_STACK) - XFREE(h, NULL, DYNAMIC_TYPE_DILITHIUM); -#endif - return ret; #else - int ret = 0; unsigned int j = 0; unsigned int c; -#if defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) - byte* h = NULL; -#else - byte h[DILITHIUM_REJ_NTT_POLY_H_SIZE]; -#endif - (void)key_h; - -#ifdef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC - h = key_h; -#elif defined(WOLFSSL_SMALL_STACK) - h = (byte*)XMALLOC(DILITHIUM_REJ_NTT_POLY_H_SIZE, NULL, - DYNAMIC_TYPE_DILITHIUM); - if (h == NULL) { - ret = MEMORY_E; - } -#endif /* WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC */ - - if (ret == 0) { - /* Generate enough SHAKE-128 output blocks to give high probability of - * being able to get 256 valid 3-byte, 23-bit values from it. */ - ret = dilithium_squeeze128(shake128, seed, DILITHIUM_GEN_A_SEED_SZ, h, - DILITHIUM_GEN_A_NBLOCKS); - } + /* Generate enough SHAKE-128 output blocks to give high probability of + * being able to get 256 valid 3-byte, 23-bit values from it. */ + ret = dilithium_squeeze128(shake128, seed, DILITHIUM_GEN_A_SEED_SZ, h, + DILITHIUM_GEN_A_NBLOCKS); if (ret == 0) { #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) /* Reading 4 bytes for 3 so need to set 1 past for last read. */ @@ -1790,7 +1771,7 @@ static int dilithium_rej_ntt_poly(wc_Shake* shake128, byte* seed, sword32* a, #endif /* Use the first 256 triplets and know we won't exceed required. */ -#ifdef WOLFSSL_DILITHIUM_NO_LARGE_CODE + #ifdef WOLFSSL_DILITHIUM_NO_LARGE_CODE for (c = 0; c < (DILITHIUM_N - 1) * 3; c += 3) { #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) /* Load 32-bit value and mask out 23 bits. */ @@ -1826,7 +1807,7 @@ static int dilithium_rej_ntt_poly(wc_Shake* shake128, byte* seed, sword32* a, } } } -#else + #else /* Do 15 bytes at a time: 255 * 3 / 15 = 51 */ for (c = 0; c < DILITHIUM_N * 3; c += 24) { #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) @@ -1923,7 +1904,7 @@ static int dilithium_rej_ntt_poly(wc_Shake* shake128, byte* seed, sword32* a, } } } -#endif + #endif /* Keep generating more blocks and using triplets until we have enough. */ while (j < DILITHIUM_N) { @@ -1956,15 +1937,60 @@ static int dilithium_rej_ntt_poly(wc_Shake* shake128, byte* seed, sword32* a, } } } +#endif -#if !defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) && defined(WOLFSSL_SMALL_STACK) - XFREE(h, NULL, DYNAMIC_TYPE_DILITHIUM); -#endif return ret; -#endif } -#if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ +#if (!defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \ + !defined(WOLFSSL_DILITHIUM_MAKE_KEY_SMALL_MEM)) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM)) || \ + (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) +/* Generate a random polynomial by rejection. + * + * @param [in, out] shake128 SHAKE-128 object. + * @param [in] seed Seed to hash to generate values. + * @param [out] a Polynomial. + * @param [in] heap Dynamic memory hint. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Negative on hash error. + */ +static int dilithium_rej_ntt_poly(wc_Shake* shake128, byte* seed, sword32* a, + void* heap) +{ + int ret; +#if defined(WOLFSSL_SMALL_STACK) + byte* h = NULL; +#else + byte h[DILITHIUM_REJ_NTT_POLY_H_SIZE]; +#endif + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) + h = (byte*)XMALLOC(DILITHIUM_REJ_NTT_POLY_H_SIZE, heap, + DYNAMIC_TYPE_DILITHIUM); + if (h == NULL) { + ret = MEMORY_E; + } +#endif + + ret = dilithium_rej_ntt_poly_ex(shake128, seed, a, h); + +#if defined(WOLFSSL_SMALL_STACK) + XFREE(h, heap, DYNAMIC_TYPE_DILITHIUM); +#endif + + return ret; +} +#endif + +#if (!defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \ + !defined(WOLFSSL_DILITHIUM_MAKE_KEY_SMALL_MEM)) || \ defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) || \ @@ -1987,11 +2013,12 @@ static int dilithium_rej_ntt_poly(wc_Shake* shake128, byte* seed, sword32* a, * @param [in] k First dimension of matrix a. * @param [in] l Second dimension of matrix a. * @param [out] a Matrix of polynomials. + * @param [in] heap Dynamic memory hint. * @return 0 on success. * @return Negative on hash error. */ static int dilithium_expand_a(wc_Shake* shake128, const byte* pub_seed, byte k, - byte l, sword32* a) + byte l, sword32* a, void* heap) { int ret = 0; byte r; @@ -2009,7 +2036,7 @@ static int dilithium_expand_a(wc_Shake* shake128, const byte* pub_seed, byte k, /* Put s into buffer to be hashed. */ seed[DILITHIUM_PUB_SEED_SZ + 0] = s; /* Step 3: Create polynomial from hashing seed. */ - ret = dilithium_rej_ntt_poly(shake128, seed, a, NULL); + ret = dilithium_rej_ntt_poly(shake128, seed, a, heap); /* Next polynomial. */ a += DILITHIUM_N; } @@ -2518,6 +2545,7 @@ static int dilithium_vec_expand_mask(wc_Shake* shake256, byte* seed, #endif #if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || !defined(WOLFSSL_DILITHIUM_NO_VERIFY) + /* Expand commit to a polynomial. * * FIPS 204. 8.3: Algorithm 23 SampleInBall(rho) @@ -2534,41 +2562,23 @@ static int dilithium_vec_expand_mask(wc_Shake* shake256, byte* seed, * 11: end for * 12: return c * - * @param [in] shake256 SHAKE-256 object. - * @param [in] seed Buffer containing seed to expand. - * @param [in] tau Number of +/- 1s in polynomial. - * @param [out] c Commit polynomial. - * @param [in] key_block Memory to use for block from key. + * @param [in] shake256 SHAKE-256 object. + * @param [in] seed Buffer containing seed to expand. + * @param [in] tau Number of +/- 1s in polynomial. + * @param [out] c Commit polynomial. + * @param [in] block Memory to use for block from key. * @return 0 on success. - * @return MEMORY_E when dynamic memory allocation fails. * @return Negative on hash error. */ -static int dilithium_sample_in_ball(wc_Shake* shake256, const byte* seed, - byte tau, sword32* c, byte* key_block) +static int dilithium_sample_in_ball_ex(wc_Shake* shake256, const byte* seed, + byte tau, sword32* c, byte* block) { int ret = 0; unsigned int k; unsigned int i; unsigned int s; -#if defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) - byte* block = NULL; -#else - byte block[DILITHIUM_GEN_C_BLOCK_BYTES]; -#endif byte signs[DILITHIUM_SIGN_BYTES]; - (void)key_block; - -#ifdef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC - block = key_block; -#elif defined(WOLFSSL_SMALL_STACK) - block = (byte*)XMALLOC(DILITHIUM_GEN_C_BLOCK_BYTES, NULL, - DYNAMIC_TYPE_DILITHIUM); - if (block == NULL) { - ret = MEMORY_E; - } -#endif - if (ret == 0) { /* Set polynomial to all zeros. */ XMEMSET(c, 0, DILITHIUM_POLY_SIZE); @@ -2613,13 +2623,57 @@ static int dilithium_sample_in_ball(wc_Shake* shake256, const byte* seed, s++; } -#if !defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) && defined(WOLFSSL_SMALL_STACK) - XFREE(block, NULL, DYNAMIC_TYPE_DILITHIUM); + return ret; +} + +#if (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM)) || \ + (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) +/* Expand commit to a polynomial. + * + * @param [in] shake256 SHAKE-256 object. + * @param [in] seed Buffer containing seed to expand. + * @param [in] tau Number of +/- 1s in polynomial. + * @param [out] c Commit polynomial. + * @param [in] heap Dynamic memory hint. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Negative on hash error. + */ +static int dilithium_sample_in_ball(wc_Shake* shake256, const byte* seed, + byte tau, sword32* c, void* heap) +{ + int ret = 0; +#if defined(WOLFSSL_SMALL_STACK) + byte* block = NULL; +#else + byte block[DILITHIUM_GEN_C_BLOCK_BYTES]; +#endif + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) + block = (byte*)XMALLOC(DILITHIUM_GEN_C_BLOCK_BYTES, heap, + DYNAMIC_TYPE_DILITHIUM); + if (block == NULL) { + ret = MEMORY_E; + } +#endif + + if (ret == 0) { + ret = dilithium_sample_in_ball_ex(shake256, seed, tau, c, block); + } + +#if defined(WOLFSSL_SMALL_STACK) + XFREE(block, heap, DYNAMIC_TYPE_DILITHIUM); #endif return ret; } #endif +#endif + /****************************************************************************** * Decompose operations ******************************************************************************/ @@ -2738,7 +2792,8 @@ static void dilithium_decompose_q32(sword32 r, sword32* r0, sword32* r1) #ifndef WOLFSSL_DILITHIUM_NO_SIGN -#ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM +#if !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM) || \ + defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A) /* Decompose vector of polynomials into high and low based on GAMMA2. * * @param [in] r Vector of polynomials to decompose. @@ -5205,6 +5260,7 @@ static void dilithium_vec_make_pos(sword32* a, byte l) */ static int dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) { +#ifndef WOLFSSL_DILITHIUM_MAKE_KEY_SMALL_MEM int ret = 0; const wc_dilithium_params* params = key->params; sword32* a = NULL; @@ -5217,7 +5273,8 @@ static int dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) #ifdef WC_DILITHIUM_CACHE_MATRIX_A #ifndef WC_DILITHIUM_FIXED_ARRAY if (key->a == NULL) { - key->a = (sword32*)XMALLOC(params->aSz, key->heap, DYNAMIC_TYPE_DILITHIUM); + key->a = (sword32*)XMALLOC(params->aSz, key->heap, + DYNAMIC_TYPE_DILITHIUM); if (key->a == NULL) { ret = MEMORY_E; } @@ -5230,7 +5287,8 @@ static int dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) #ifdef WC_DILITHIUM_CACHE_PRIV_VECTORS #ifndef WC_DILITHIUM_FIXED_ARRAY if ((ret == 0) && (key->s1 == NULL)) { - key->s1 = (sword32*)XMALLOC(params->aSz, key->heap, DYNAMIC_TYPE_DILITHIUM); + key->s1 = (sword32*)XMALLOC(params->aSz, key->heap, + DYNAMIC_TYPE_DILITHIUM); if (key->s1 == NULL) { ret = MEMORY_E; } @@ -5263,7 +5321,7 @@ static int dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) s2 = s1 + params->s1Sz / sizeof(*s1); t = s2 + params->s2Sz / sizeof(*s2); #ifndef WC_DILITHIUM_CACHE_MATRIX_A - a = t + params->s2Sz / sizeof(*s2); + a = t + params->s2Sz / sizeof(*t); #endif } } @@ -5281,7 +5339,7 @@ static int dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) /* Step 3: Expand public seed into a matrix of polynomials. */ ret = dilithium_expand_a(&key->shake, pub_seed, params->k, params->l, - a); + a, key->heap); } if (ret == 0) { byte* priv_seed = key->k + DILITHIUM_PUB_SEED_SZ; @@ -5343,6 +5401,210 @@ static int dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) XFREE(s1, key->heap, DYNAMIC_TYPE_DILITHIUM); #endif return ret; +#else + int ret = 0; + const wc_dilithium_params* params = key->params; + sword32* a = NULL; + sword32* s1 = NULL; + sword32* s2 = NULL; + sword32* t = NULL; +#ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + sword64* t64 = NULL; +#endif + byte* h = NULL; + byte* pub_seed = key->k; + unsigned int r; + unsigned int s; + + /* Allocate memory for large intermediates. */ + if (ret == 0) { + unsigned int allocSz; + + /* s1-l, s2-k, t-k, a-1 */ + allocSz = params->s1Sz + params->s2Sz + params->s2Sz + + DILITHIUM_REJ_NTT_POLY_H_SIZE + DILITHIUM_POLY_SIZE; + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + /* t64 */ + allocSz += DILITHIUM_POLY_SIZE * 2; + #endif + s1 = (sword32*)XMALLOC(allocSz, key->heap, DYNAMIC_TYPE_DILITHIUM); + if (s1 == NULL) { + ret = MEMORY_E; + } + else { + s2 = s1 + params->s1Sz / sizeof(*s1); + t = s2 + params->s2Sz / sizeof(*s2); + h = (byte*)(t + params->s2Sz / sizeof(*t)); + a = (sword32*)(h + DILITHIUM_REJ_NTT_POLY_H_SIZE); + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + t64 = (sword64*)(a + DILITHIUM_N); + #endif + } + } + + if (ret == 0) { + /* Step 2: Create public seed, private seed and K from seed. + * Step 9; Alg 18, Step 1: Public seed is placed into private key. */ + ret = dilithium_shake256(&key->shake, seed, DILITHIUM_SEED_SZ, pub_seed, + DILITHIUM_SEEDS_SZ); + } + if (ret == 0) { + byte* priv_seed = key->k + DILITHIUM_PUB_SEED_SZ; + + /* Step 7; Alg 16 Step 1: Copy public seed into public key. */ + XMEMCPY(key->p, pub_seed, DILITHIUM_PUB_SEED_SZ); + + /* Step 4: Expand private seed into to vectors of polynomials. */ + ret = dilithium_expand_s(&key->shake, priv_seed, params->eta, s1, + params->l, s2, params->k); + } + if (ret == 0) { + byte* k = pub_seed + DILITHIUM_PUB_SEED_SZ; + byte* tr = k + DILITHIUM_K_SZ; + byte* s1p = tr + DILITHIUM_TR_SZ; + byte* s2p = s1p + params->s1EncSz; + byte* t0 = s2p + params->s2EncSz; + byte* t1 = key->p + DILITHIUM_PUB_SEED_SZ; + byte aseed[DILITHIUM_GEN_A_SEED_SZ]; + sword32* s2t = s2; + sword32* tt = t; + + /* Step 9: Move k down to after public seed. */ + XMEMCPY(k, k + DILITHIUM_PRIV_SEED_SZ, DILITHIUM_K_SZ); + /* Step 9. Alg 18 Steps 2-4: Encode s1 into private key. */ + dilthium_vec_encode_eta_bits(s1, params->l, params->eta, s1p); + /* Step 9. Alg 18 Steps 5-7: Encode s2 into private key. */ + dilthium_vec_encode_eta_bits(s2, params->k, params->eta, s2p); + + /* Step 5: NTT(s1) */ + dilithium_vec_ntt_small(s1, params->l); + /* Step 5: t <- NTT-1(A_circum o NTT(s1)) + s2 */ + XMEMCPY(aseed, pub_seed, DILITHIUM_PUB_SEED_SZ); + for (r = 0; (ret == 0) && (r < params->k); r++) { + sword32* s1t = s1; + unsigned int e; + + /* Put r/i into buffer to be hashed. */ + aseed[DILITHIUM_PUB_SEED_SZ + 1] = r; + for (s = 0; (ret == 0) && (s < params->l); s++) { + + /* Put s into buffer to be hashed. */ + aseed[DILITHIUM_PUB_SEED_SZ + 0] = s; + /* Step 3: Expand public seed into a matrix of polynomials. */ + ret = dilithium_rej_ntt_poly_ex(&key->shake, aseed, a, h); + if (ret != 0) { + break; + } + /* Matrix multiply. */ + #ifndef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + if (s == 0) { + #ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + tt[e] = dilithium_mont_red((sword64)a[e] * s1t[e]); + } + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + tt[e+0] = dilithium_mont_red((sword64)a[e+0]*s1t[e+0]); + tt[e+1] = dilithium_mont_red((sword64)a[e+1]*s1t[e+1]); + tt[e+2] = dilithium_mont_red((sword64)a[e+2]*s1t[e+2]); + tt[e+3] = dilithium_mont_red((sword64)a[e+3]*s1t[e+3]); + tt[e+4] = dilithium_mont_red((sword64)a[e+4]*s1t[e+4]); + tt[e+5] = dilithium_mont_red((sword64)a[e+5]*s1t[e+5]); + tt[e+6] = dilithium_mont_red((sword64)a[e+6]*s1t[e+6]); + tt[e+7] = dilithium_mont_red((sword64)a[e+7]*s1t[e+7]); + } + #endif + } + else { + #ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + tt[e] += dilithium_mont_red((sword64)a[e] * s1t[e]); + } + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + tt[e+0] += dilithium_mont_red((sword64)a[e+0]*s1t[e+0]); + tt[e+1] += dilithium_mont_red((sword64)a[e+1]*s1t[e+1]); + tt[e+2] += dilithium_mont_red((sword64)a[e+2]*s1t[e+2]); + tt[e+3] += dilithium_mont_red((sword64)a[e+3]*s1t[e+3]); + tt[e+4] += dilithium_mont_red((sword64)a[e+4]*s1t[e+4]); + tt[e+5] += dilithium_mont_red((sword64)a[e+5]*s1t[e+5]); + tt[e+6] += dilithium_mont_red((sword64)a[e+6]*s1t[e+6]); + tt[e+7] += dilithium_mont_red((sword64)a[e+7]*s1t[e+7]); + } + #endif + } + #else + if (s == 0) { + #ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + t64[e] = (sword64)a[e] * s1t[e]; + } + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + t64[e+0] = (sword64)a[e+0] * s1t[e+0]; + t64[e+1] = (sword64)a[e+1] * s1t[e+1]; + t64[e+2] = (sword64)a[e+2] * s1t[e+2]; + t64[e+3] = (sword64)a[e+3] * s1t[e+3]; + t64[e+4] = (sword64)a[e+4] * s1t[e+4]; + t64[e+5] = (sword64)a[e+5] * s1t[e+5]; + t64[e+6] = (sword64)a[e+6] * s1t[e+6]; + t64[e+7] = (sword64)a[e+7] * s1t[e+7]; + } + #endif + } + else { + #ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + t64[e] += (sword64)a[e] * s1t[e]; + } + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + t64[e+0] += (sword64)a[e+0] * s1t[e+0]; + t64[e+1] += (sword64)a[e+1] * s1t[e+1]; + t64[e+2] += (sword64)a[e+2] * s1t[e+2]; + t64[e+3] += (sword64)a[e+3] * s1t[e+3]; + t64[e+4] += (sword64)a[e+4] * s1t[e+4]; + t64[e+5] += (sword64)a[e+5] * s1t[e+5]; + t64[e+6] += (sword64)a[e+6] * s1t[e+6]; + t64[e+7] += (sword64)a[e+7] * s1t[e+7]; + } + #endif + } + #endif + /* Next polynomial. */ + s1t += DILITHIUM_N; + } + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + for (e = 0; e < DILITHIUM_N; e++) { + tt[e] = dilithium_mont_red(t64[e]); + } + #endif + dilithium_invntt(tt); + dilithium_add(tt, s2t); + /* Make positive for decomposing. */ + dilithium_make_pos(tt); + + tt += DILITHIUM_N; + s2t += DILITHIUM_N; + } + + /* Step 6, Step 7, Step 9. Alg 16 Steps 2-4, Alg 18 Steps 8-10. + * Decompose t in t0 and t1 and encode into public and private key. + */ + dilithium_vec_encode_t0_t1(t, params->k, t0, t1); + /* Step 8. Alg 18, Step 1: Hash public key into private key. */ + ret = dilithium_shake256(&key->shake, key->p, params->pkSz, tr, + DILITHIUM_TR_SZ); + } + if (ret == 0) { + /* Public key and private key are available. */ + key->prvKeySet = 1; + key->pubKeySet = 1; + } + + XFREE(s1, key->heap, DYNAMIC_TYPE_DILITHIUM); + return ret; +#endif } /* Make a key from a random seed. @@ -5376,6 +5638,7 @@ static int dilithium_make_key(dilithium_key* key, WC_RNG* rng) #ifndef WOLFSSL_DILITHIUM_NO_SIGN #if !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM) || \ + defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC) || \ defined(WC_DILITHIUM_CACHE_PRIV_VECTORS) /* Decode, from private key, and NTT private key vectors s1, s2, and t0. * @@ -5590,7 +5853,7 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, { /* Step 5: Create the matrix A from the public seed. */ ret = dilithium_expand_a(&key->shake, pub_seed, params->k, - params->l, a); + params->l, a, key->heap); #ifdef WC_DILITHIUM_CACHE_MATRIX_A key->aSet = (ret == 0); #endif @@ -5655,7 +5918,7 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, if (ret == 0) { /* Step 17: Compute c from first 256 bits of commit. */ ret = dilithium_sample_in_ball(&key->shake, commit, - params->tau, c, NULL); + params->tau, c, key->heap); } if (ret == 0) { sword32 hi; @@ -5747,10 +6010,18 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, sword32* c = NULL; sword32* z = NULL; sword32* ct0 = NULL; +#ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + sword64* t64 = NULL; +#endif + byte* blocks = NULL; byte data[DILITHIUM_RND_SZ + DILITHIUM_MU_SZ]; byte* mu = data + DILITHIUM_RND_SZ; byte priv_rand_seed[DILITHIUM_Y_SEED_SZ]; byte* h = sig + params->lambda * 2 + params->zEncSz; +#ifdef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A + byte maxK = (byte)min(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A, + params->k); +#endif /* Check the signature buffer isn't too small. */ if ((ret == 0) && (*sigLen < params->sigSz)) { @@ -5765,24 +6036,55 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, if (ret == 0) { unsigned int allocSz; - /* y-l, w0-k, w1-k, c-1, s1-1, A-1 */ - allocSz = params->s1Sz + params->s2Sz + params->s2Sz + + /* y-l, w0-k, w1-k, blocks, c-1, z-1, A-1 */ + allocSz = params->s1Sz + params->s2Sz + params->s2Sz + + DILITHIUM_REJ_NTT_POLY_H_SIZE + DILITHIUM_POLY_SIZE + DILITHIUM_POLY_SIZE + DILITHIUM_POLY_SIZE; + #ifdef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC + allocSz += params->s1Sz + params->s2Sz + params->s2Sz; + #elif defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A) + allocSz += maxK * params->l * DILITHIUM_POLY_SIZE; + #endif + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + allocSz += DILITHIUM_POLY_SIZE * 2; + #endif y = (sword32*)XMALLOC(allocSz, key->heap, DYNAMIC_TYPE_DILITHIUM); if (y == NULL) { ret = MEMORY_E; } else { - w0 = y + params->s1Sz / sizeof(*y_ntt); - w1 = w0 + params->s2Sz / sizeof(*w0); - c = w1 + params->s2Sz / sizeof(*w1); - s1 = c + DILITHIUM_N; - a = s1 + DILITHIUM_N; - s2 = s1; - t0 = s1; - ct0 = s1; - z = s1; - y_ntt = s1; + w0 = y + params->s1Sz / sizeof(*y_ntt); + w1 = w0 + params->s2Sz / sizeof(*w0); + blocks = (byte*)(w1 + params->s2Sz / sizeof(*w1)); + c = (sword32*)(blocks + DILITHIUM_REJ_NTT_POLY_H_SIZE); + z = c + DILITHIUM_N; + a = z + DILITHIUM_N; + ct0 = z; + #if defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A) + y_ntt = w0; + s1 = z; + s2 = z; + t0 = z; + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + t64 = (sword64*)(a + (1 + maxK * params->l) * DILITHIUM_N); + #endif + #elif defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC) + y_ntt = z; + s1 = a + DILITHIUM_N; + s2 = s1 + params->s1Sz / sizeof(*s1); + t0 = s2 + params->s2Sz / sizeof(*s2); + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + t64 = (sword64*)(t0 + params->s2Sz / sizeof(*t0)); + #endif + #else + y_ntt = z; + s1 = z; + s2 = z; + t0 = z; + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + t64 = (sword64*)(a + DILITHIUM_N); + #endif + #endif } } @@ -5800,23 +6102,43 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, DILITHIUM_RND_SZ + DILITHIUM_MU_SZ, priv_rand_seed, DILITHIUM_PRIV_RAND_SEED_SZ); } +#ifdef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC + if (ret == 0) { + dilithium_make_priv_vecs(key, s1, s2, t0); + } +#endif +#ifdef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A + if (ret == 0) { + /* Step 5: Create the matrix A from the public seed. */ + ret = dilithium_expand_a(&key->shake, pub_seed, maxK, params->l, a, + key->heap); + } +#endif if (ret == 0) { word16 kappa = 0; int valid; /* Step 11: Start rejection sampling loop */ do { + byte aseed[DILITHIUM_GEN_A_SEED_SZ]; byte w1e[DILITHIUM_MAX_W1_ENC_SZ]; sword32* w = w1; byte* commit = sig; byte r; byte s; - byte aseed[DILITHIUM_GEN_A_SEED_SZ]; sword32 hi; - sword32* at = a; sword32* wt = w; sword32* w0t = w0; sword32* w1t = w1; + sword32* at = a; + + #ifdef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A + w0t += WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A * DILITHIUM_N; + w1t += WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A * DILITHIUM_N; + wt += WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A * DILITHIUM_N; + at += WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A * params->l * + DILITHIUM_N; + #endif valid = 1; /* Step 12: Compute vector y from private random seed and kappa. */ @@ -5827,13 +6149,33 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, (1 << params->gamma1_bits) - params->beta); #endif + #ifdef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A + /* Step 13: NTT-1(A o NTT(y)) */ + XMEMCPY(y_ntt, y, params->s1Sz); + dilithium_vec_ntt(y_ntt, params->l); + dilithium_matrix_mul(w, a, y_ntt, maxK, params->l); + dilithium_vec_invntt(w, maxK); + /* Step 14, Step 22: Make values positive and decompose. */ + dilithium_vec_make_pos(w, maxK); + dilithium_vec_decompose(w, maxK, params->gamma2, w0, w1); + #endif /* Step 5: Create the matrix A from the public seed. */ /* Copy the seed into a buffer that has space for s and r. */ XMEMCPY(aseed, pub_seed, DILITHIUM_PUB_SEED_SZ); + #ifdef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A + r = WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A; + #else + r = 0; + #endif /* Alg 26. Step 1: Loop over first dimension of matrix. */ - for (r = 0; (ret == 0) && valid && (r < params->k); r++) { + for (; (ret == 0) && valid && (r < params->k); r++) { unsigned int e; sword32* yt = y; + #ifdef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A + sword32* y_ntt_t = z; + #else + sword32* y_ntt_t = y_ntt; + #endif /* Put r/i into buffer to be hashed. */ aseed[DILITHIUM_PUB_SEED_SZ + 1] = r; @@ -5842,29 +6184,115 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, /* Put s into buffer to be hashed. */ aseed[DILITHIUM_PUB_SEED_SZ + 0] = s; /* Alg 26. Step 3: Create polynomial from hashing seed. */ - ret = dilithium_rej_ntt_poly(&key->shake, aseed, at, - NULL); + ret = dilithium_rej_ntt_poly_ex(&key->shake, aseed, at, + blocks); if (ret != 0) { break; } - XMEMCPY(y_ntt, yt, DILITHIUM_POLY_SIZE); - dilithium_ntt(y_ntt); + XMEMCPY(y_ntt_t, yt, DILITHIUM_POLY_SIZE); + dilithium_ntt(y_ntt_t); /* Matrix multiply. */ + #ifndef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 if (s == 0) { + #ifdef WOLFSSL_DILITHIUM_SMALL for (e = 0; e < DILITHIUM_N; e++) { wt[e] = dilithium_mont_red((sword64)at[e] * - y_ntt[e]); + y_ntt_t[e]); } + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + wt[e + 0] = dilithium_mont_red((sword64)at[e + 0] * + y_ntt_t[e + 0]); + wt[e + 1] = dilithium_mont_red((sword64)at[e + 1] * + y_ntt_t[e + 1]); + wt[e + 2] = dilithium_mont_red((sword64)at[e + 2] * + y_ntt_t[e + 2]); + wt[e + 3] = dilithium_mont_red((sword64)at[e + 3] * + y_ntt_t[e + 3]); + wt[e + 4] = dilithium_mont_red((sword64)at[e + 4] * + y_ntt_t[e + 4]); + wt[e + 5] = dilithium_mont_red((sword64)at[e + 5] * + y_ntt_t[e + 5]); + wt[e + 6] = dilithium_mont_red((sword64)at[e + 6] * + y_ntt_t[e + 6]); + wt[e + 7] = dilithium_mont_red((sword64)at[e + 7] * + y_ntt_t[e + 7]); + } + #endif } else { + #ifdef WOLFSSL_DILITHIUM_SMALL for (e = 0; e < DILITHIUM_N; e++) { wt[e] += dilithium_mont_red((sword64)at[e] * - y_ntt[e]); + y_ntt_t[e]); } + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + wt[e + 0] += dilithium_mont_red((sword64)at[e + 0] * + y_ntt_t[e + 0]); + wt[e + 1] += dilithium_mont_red((sword64)at[e + 1] * + y_ntt_t[e + 1]); + wt[e + 2] += dilithium_mont_red((sword64)at[e + 2] * + y_ntt_t[e + 2]); + wt[e + 3] += dilithium_mont_red((sword64)at[e + 3] * + y_ntt_t[e + 3]); + wt[e + 4] += dilithium_mont_red((sword64)at[e + 4] * + y_ntt_t[e + 4]); + wt[e + 5] += dilithium_mont_red((sword64)at[e + 5] * + y_ntt_t[e + 5]); + wt[e + 6] += dilithium_mont_red((sword64)at[e + 6] * + y_ntt_t[e + 6]); + wt[e + 7] += dilithium_mont_red((sword64)at[e + 7] * + y_ntt_t[e + 7]); + } + #endif } + #else + if (s == 0) { + #ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + t64[e] = (sword64)at[e] * y_ntt_t[e]; + } + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + t64[e+0] = (sword64)at[e+0] * y_ntt_t[e+0]; + t64[e+1] = (sword64)at[e+1] * y_ntt_t[e+1]; + t64[e+2] = (sword64)at[e+2] * y_ntt_t[e+2]; + t64[e+3] = (sword64)at[e+3] * y_ntt_t[e+3]; + t64[e+4] = (sword64)at[e+4] * y_ntt_t[e+4]; + t64[e+5] = (sword64)at[e+5] * y_ntt_t[e+5]; + t64[e+6] = (sword64)at[e+6] * y_ntt_t[e+6]; + t64[e+7] = (sword64)at[e+7] * y_ntt_t[e+7]; + } + #endif + } + else { + #ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + t64[e] += (sword64)at[e] * y_ntt_t[e]; + } + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + t64[e+0] += (sword64)at[e+0] * y_ntt_t[e+0]; + t64[e+1] += (sword64)at[e+1] * y_ntt_t[e+1]; + t64[e+2] += (sword64)at[e+2] * y_ntt_t[e+2]; + t64[e+3] += (sword64)at[e+3] * y_ntt_t[e+3]; + t64[e+4] += (sword64)at[e+4] * y_ntt_t[e+4]; + t64[e+5] += (sword64)at[e+5] * y_ntt_t[e+5]; + t64[e+6] += (sword64)at[e+6] * y_ntt_t[e+6]; + t64[e+7] += (sword64)at[e+7] * y_ntt_t[e+7]; + } + #endif + } + #endif /* Next polynomial. */ yt += DILITHIUM_N; } + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + for (e = 0; e < DILITHIUM_N; e++) { + wt[e] = dilithium_mont_red(t64[e]); + } + #endif dilithium_invntt(wt); /* Step 14, Step 22: Make values positive and decompose. */ dilithium_make_pos(wt); @@ -5896,7 +6324,9 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, } if ((ret == 0) && valid) { sword32* yt = y; + #ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC const byte* s1pt = s1p; + #endif byte* ze = sig + params->lambda * 2; /* Step 15: Encode w1. */ @@ -5907,8 +6337,8 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, w1e, params->w1EncSz, commit, 2 * params->lambda); if (ret == 0) { /* Step 17: Compute c from first 256 bits of commit. */ - ret = dilithium_sample_in_ball(&key->shake, commit, - params->tau, c, NULL); + ret = dilithium_sample_in_ball_ex(&key->shake, commit, + params->tau, c, blocks); } if (ret == 0) { /* Step 18: NTT(c). */ @@ -5916,6 +6346,7 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, } for (s = 0; (ret == 0) && valid && (s < params->l); s++) { + #ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC #if !defined(WOLFSSL_NO_ML_DSA_44) || \ !defined(WOLFSSL_NO_ML_DSA_87) /* -2..2 */ @@ -5933,6 +6364,9 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, #endif dilithium_ntt_small(s1); dilithium_mul(z, c, s1); + #else + dilithium_mul(z, c, s1 + s * DILITHIUM_N); + #endif /* Step 19: cs1 = NTT-1(c o s1) */ dilithium_invntt(z); /* Step 21: z = y + cs1 */ @@ -5969,13 +6403,16 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, } if ((ret == 0) && valid) { const byte* t0pt = t0p; + #ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC const byte* s2pt = s2p; + #endif sword32* cs2 = ct0; w0t = w0; w1t = w1; byte idx = 0; for (r = 0; valid && (r < params->k); r++) { + #ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC #if !defined(WOLFSSL_NO_ML_DSA_44) || \ !defined(WOLFSSL_NO_ML_DSA_87) /* -2..2 */ @@ -5990,10 +6427,14 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, dilithium_decode_eta_4_bits(s2pt, s2); s2pt += DILITHIUM_N / 2; } - #endif + #endif dilithium_ntt_small(s2); /* Step 20: cs2 = NTT-1(c o s2) */ dilithium_mul(cs2, c, s2); + #else + /* Step 20: cs2 = NTT-1(c o s2) */ + dilithium_mul(cs2, c, s2 + r * DILITHIUM_N); + #endif dilithium_invntt(cs2); /* Step 22: w0 - cs2 */ dilithium_sub(w0t, cs2); @@ -6002,11 +6443,16 @@ static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, hi = params->gamma2 - params->beta; valid = dilithium_check_low(w0t, hi); if (valid) { + #ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC dilithium_decode_t0(t0pt, t0); dilithium_ntt(t0); /* Step 25: ct0 = NTT-1(c o t0) */ dilithium_mul(ct0, c, t0); + #else + /* Step 25: ct0 = NTT-1(c o t0) */ + dilithium_mul(ct0, c, t0 + r * DILITHIUM_N); + #endif dilithium_invntt(ct0); /* Step 27: Check ct0 has low enough values. */ valid = dilithium_check_low(ct0, params->gamma2); @@ -6199,7 +6645,8 @@ static int dilithium_verify_msg(dilithium_key* key, const byte* msg, #ifdef WC_DILITHIUM_CACHE_MATRIX_A #ifndef WC_DILITHIUM_FIXED_ARRAY if ((ret == 0) && (key->a == NULL)) { - key->a = (sword32*)XMALLOC(params->aSz, key->heap, DYNAMIC_TYPE_DILITHIUM); + key->a = (sword32*)XMALLOC(params->aSz, key->heap, + DYNAMIC_TYPE_DILITHIUM); if (key->a == NULL) { ret = MEMORY_E; } @@ -6212,7 +6659,8 @@ static int dilithium_verify_msg(dilithium_key* key, const byte* msg, #ifdef WC_DILITHIUM_CACHE_PUB_VECTORS #ifndef WC_DILITHIUM_FIXED_ARRAY if ((ret == 0) && (key->t1 == NULL)) { - key->t1 = (sword32*)XMALLOC(params->s2Sz, key->heap, DYNAMIC_TYPE_DILITHIUM); + key->t1 = (sword32*)XMALLOC(params->s2Sz, key->heap, + DYNAMIC_TYPE_DILITHIUM); if (key->t1 == NULL) { ret = MEMORY_E; } @@ -6277,7 +6725,7 @@ static int dilithium_verify_msg(dilithium_key* key, const byte* msg, { /* Step 5: Expand pub seed to compute matrix A. */ ret = dilithium_expand_a(&key->shake, pub_seed, params->k, - params->l, a); + params->l, a, key->heap); #ifdef WC_DILITHIUM_CACHE_MATRIX_A /* Whether we have cached A is dependent on success of operation. */ key->aSet = (ret == 0); @@ -6295,9 +6743,9 @@ static int dilithium_verify_msg(dilithium_key* key, const byte* msg, mu, DILITHIUM_MU_SZ); } if ((ret == 0) && valid) { - /* Step 9: Compute c from first 256 bits of commit. */ - ret = dilithium_sample_in_ball(&key->shake, commit, params->tau, c, - NULL); + /* Step 9: Compute c from first 256 bits of commit. */ + ret = dilithium_sample_in_ball(&key->shake, commit, params->tau, c, + key->heap); } if ((ret == 0) && valid) { /* Step 10: w = NTT-1(A o NTT(z) - NTT(c) o NTT(t1)) */ @@ -6336,14 +6784,19 @@ static int dilithium_verify_msg(dilithium_key* key, const byte* msg, sword32* c = NULL; sword32* z = NULL; sword32* w = NULL; +#ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + sword64* t64 = NULL; +#endif +#ifndef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC + byte* block = NULL; +#endif byte tr[DILITHIUM_TR_SZ]; byte* mu = tr; byte* w1e = NULL; byte* commit_calc = tr; int valid = 0; sword32 hi; - byte i; - unsigned int j; + unsigned int r; byte o; byte* encW1; byte* seed = tr; @@ -6361,17 +6814,27 @@ static int dilithium_verify_msg(dilithium_key* key, const byte* msg, /* Allocate memory for large intermediates. */ if (ret == 0) { /* z, c, w, t1, w1e. */ - z = (sword32*)XMALLOC(params->s1Sz + 3 * DILITHIUM_POLY_SIZE + - DILITHIUM_MAX_W1_ENC_SZ, key->heap, DYNAMIC_TYPE_DILITHIUM); + unsigned int allocSz; + + allocSz = params->s1Sz + 3 * DILITHIUM_POLY_SIZE + + DILITHIUM_REJ_NTT_POLY_H_SIZE + params->w1EncSz; + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + allocSz += DILITHIUM_POLY_SIZE * 2; + #endif + z = (sword32*)XMALLOC(allocSz, key->heap, DYNAMIC_TYPE_DILITHIUM); if (z == NULL) { ret = MEMORY_E; } else { - c = z + params->s1Sz / sizeof(*t1); - w = c + DILITHIUM_N; - t1 = w + DILITHIUM_N; - w1e = (byte*)(t1 + DILITHIUM_N); - a = t1; + c = z + params->s1Sz / sizeof(*t1); + w = c + DILITHIUM_N; + t1 = w + DILITHIUM_N; + block = (byte*)(t1 + DILITHIUM_N); + w1e = block + DILITHIUM_REJ_NTT_POLY_H_SIZE; + a = t1; + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + t64 = (sword64*)(w1e + params->w1EncSz); + #endif } } #else @@ -6382,6 +6845,9 @@ static int dilithium_verify_msg(dilithium_key* key, const byte* msg, t1 = key->t1; w1e = key->w1e; a = t1; + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + t64 = key->t64; + #endif } #endif @@ -6398,11 +6864,11 @@ static int dilithium_verify_msg(dilithium_key* key, const byte* msg, /* Step 9: Compute c from first 256 bits of commit. */ #ifdef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC - ret = dilithium_sample_in_ball(&key->shake, commit, params->tau, c, + ret = dilithium_sample_in_ball_ex(&key->shake, commit, params->tau, c, key->block); #else - ret = dilithium_sample_in_ball(&key->shake, commit, params->tau, c, - NULL); + ret = dilithium_sample_in_ball_ex(&key->shake, commit, params->tau, c, + block); #endif } if ((ret == 0) && valid) { @@ -6414,8 +6880,9 @@ static int dilithium_verify_msg(dilithium_key* key, const byte* msg, /* Copy the seed into a buffer that has space for s and r. */ XMEMCPY(seed, pub_seed, DILITHIUM_PUB_SEED_SZ); /* Step 1: Loop over first dimension of matrix. */ - for (i = 0; (ret == 0) && (i < params->k); i++) { - byte s; + for (r = 0; (ret == 0) && (r < params->k); r++) { + unsigned int s; + unsigned int e; const sword32* zt = z; /* Step 1: Decode and NTT vector t1. */ @@ -6425,80 +6892,123 @@ static int dilithium_verify_msg(dilithium_key* key, const byte* msg, /* Step 10: - NTT(c) o NTT(t1)) */ dilithium_ntt(w); -#ifdef WOLFSSL_DILITHIUM_SMALL - for (j = 0; j < DILITHIUM_N; j++) { - w[j] = -dilithium_mont_red((sword64)c[j] * w[j]); + #ifndef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + #ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + w[e] = -dilithium_mont_red((sword64)c[e] * w[e]); } -#else - for (j = 0; j < DILITHIUM_N; j += 8) { - w[j+0] = -dilithium_mont_red((sword64)c[j+0] * w[j+0]); - w[j+1] = -dilithium_mont_red((sword64)c[j+1] * w[j+1]); - w[j+2] = -dilithium_mont_red((sword64)c[j+2] * w[j+2]); - w[j+3] = -dilithium_mont_red((sword64)c[j+3] * w[j+3]); - w[j+4] = -dilithium_mont_red((sword64)c[j+4] * w[j+4]); - w[j+5] = -dilithium_mont_red((sword64)c[j+5] * w[j+5]); - w[j+6] = -dilithium_mont_red((sword64)c[j+6] * w[j+6]); - w[j+7] = -dilithium_mont_red((sword64)c[j+7] * w[j+7]); + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + w[e+0] = -dilithium_mont_red((sword64)c[e+0] * w[e+0]); + w[e+1] = -dilithium_mont_red((sword64)c[e+1] * w[e+1]); + w[e+2] = -dilithium_mont_red((sword64)c[e+2] * w[e+2]); + w[e+3] = -dilithium_mont_red((sword64)c[e+3] * w[e+3]); + w[e+4] = -dilithium_mont_red((sword64)c[e+4] * w[e+4]); + w[e+5] = -dilithium_mont_red((sword64)c[e+5] * w[e+5]); + w[e+6] = -dilithium_mont_red((sword64)c[e+6] * w[e+6]); + w[e+7] = -dilithium_mont_red((sword64)c[e+7] * w[e+7]); } -#endif + #endif + #else + #ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + t64[e] = -(sword64)c[e] * w[e]; + } + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + t64[e+0] = -(sword64)c[e+0] * w[e+0]; + t64[e+1] = -(sword64)c[e+1] * w[e+1]; + t64[e+2] = -(sword64)c[e+2] * w[e+2]; + t64[e+3] = -(sword64)c[e+3] * w[e+3]; + t64[e+4] = -(sword64)c[e+4] * w[e+4]; + t64[e+5] = -(sword64)c[e+5] * w[e+5]; + t64[e+6] = -(sword64)c[e+6] * w[e+6]; + t64[e+7] = -(sword64)c[e+7] * w[e+7]; + } + #endif + #endif /* Step 5: Expand pub seed to compute matrix A. */ /* Put r into buffer to be hashed. */ - seed[DILITHIUM_PUB_SEED_SZ + 1] = i; + seed[DILITHIUM_PUB_SEED_SZ + 1] = r; for (s = 0; (ret == 0) && (s < params->l); s++) { /* Put s into buffer to be hashed. */ seed[DILITHIUM_PUB_SEED_SZ + 0] = s; /* Step 3: Create polynomial from hashing seed. */ #ifdef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC - ret = dilithium_rej_ntt_poly(&key->shake, seed, a, key->h); + ret = dilithium_rej_ntt_poly_ex(&key->shake, seed, a, key->h); #else - ret = dilithium_rej_ntt_poly(&key->shake, seed, a, NULL); + ret = dilithium_rej_ntt_poly_ex(&key->shake, seed, a, block); #endif /* Step 10: w = A o NTT(z) - NTT(c) o NTT(t1) */ -#ifdef WOLFSSL_DILITHIUM_SMALL - for (j = 0; j < DILITHIUM_N; j++) { - w[j] += dilithium_mont_red((sword64)a[j] * zt[j]); + #ifndef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + #ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + w[e] += dilithium_mont_red((sword64)a[e] * zt[e]); } -#else - for (j = 0; j < DILITHIUM_N; j += 8) { - w[j+0] += dilithium_mont_red((sword64)a[j+0] * zt[j+0]); - w[j+1] += dilithium_mont_red((sword64)a[j+1] * zt[j+1]); - w[j+2] += dilithium_mont_red((sword64)a[j+2] * zt[j+2]); - w[j+3] += dilithium_mont_red((sword64)a[j+3] * zt[j+3]); - w[j+4] += dilithium_mont_red((sword64)a[j+4] * zt[j+4]); - w[j+5] += dilithium_mont_red((sword64)a[j+5] * zt[j+5]); - w[j+6] += dilithium_mont_red((sword64)a[j+6] * zt[j+6]); - w[j+7] += dilithium_mont_red((sword64)a[j+7] * zt[j+7]); + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + w[e+0] += dilithium_mont_red((sword64)a[e+0] * zt[e+0]); + w[e+1] += dilithium_mont_red((sword64)a[e+1] * zt[e+1]); + w[e+2] += dilithium_mont_red((sword64)a[e+2] * zt[e+2]); + w[e+3] += dilithium_mont_red((sword64)a[e+3] * zt[e+3]); + w[e+4] += dilithium_mont_red((sword64)a[e+4] * zt[e+4]); + w[e+5] += dilithium_mont_red((sword64)a[e+5] * zt[e+5]); + w[e+6] += dilithium_mont_red((sword64)a[e+6] * zt[e+6]); + w[e+7] += dilithium_mont_red((sword64)a[e+7] * zt[e+7]); } -#endif + #endif + #else + #ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + t64[e] += (sword64)a[e] * zt[e]; + } + #else + for (e = 0; e < DILITHIUM_N; e += 8) { + t64[e+0] += (sword64)a[e+0] * zt[e+0]; + t64[e+1] += (sword64)a[e+1] * zt[e+1]; + t64[e+2] += (sword64)a[e+2] * zt[e+2]; + t64[e+3] += (sword64)a[e+3] * zt[e+3]; + t64[e+4] += (sword64)a[e+4] * zt[e+4]; + t64[e+5] += (sword64)a[e+5] * zt[e+5]; + t64[e+6] += (sword64)a[e+6] * zt[e+6]; + t64[e+7] += (sword64)a[e+7] * zt[e+7]; + } + #endif + #endif /* Next polynomial. */ zt += DILITHIUM_N; } + #ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + for (e = 0; e < DILITHIUM_N; e++) { + w[e] = dilithium_mont_red(t64[e]); + } + #endif /* Step 10: w = NTT-1(A o NTT(z) - NTT(c) o NTT(t1)) */ dilithium_invntt(w); -#ifndef WOLFSSL_NO_ML_DSA_44 + #ifndef WOLFSSL_NO_ML_DSA_44 if (params->gamma2 == DILITHIUM_Q_LOW_88) { /* Step 11: Use hint to give full w1. */ - dilithium_use_hint_88(w, h, i, &o); + dilithium_use_hint_88(w, h, r, &o); /* Step 12: Encode w1. */ dilithium_encode_w1_88(w, encW1); encW1 += DILITHIUM_Q_HI_88_ENC_BITS * 2 * DILITHIUM_N / 16; } else -#endif -#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) + #endif + #if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) if (params->gamma2 == DILITHIUM_Q_LOW_32) { /* Step 11: Use hint to give full w1. */ - dilithium_use_hint_32(w, h, params->omega, i, &o); + dilithium_use_hint_32(w, h, params->omega, r, &o); /* Step 12: Encode w1. */ dilithium_encode_w1_32(w, encW1); encW1 += DILITHIUM_Q_HI_32_ENC_BITS * 2 * DILITHIUM_N / 16; } else -#endif + #endif { } } @@ -6541,13 +7051,13 @@ static int oqs_dilithium_make_key(dilithium_key* key, WC_RNG* rng) int ret = 0; OQS_SIG *oqssig = NULL; - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_44_ipd); } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_65_ipd); } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_87_ipd); } else { @@ -6589,13 +7099,13 @@ static int oqs_dilithium_sign_msg(const byte* msg, word32 msgLen, byte* sig, } if (ret == 0) { - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_44_ipd); } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_65_ipd); } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_87_ipd); } else { @@ -6609,15 +7119,18 @@ static int oqs_dilithium_sign_msg(const byte* msg, word32 msgLen, byte* sig, /* check and set up out length */ if (ret == 0) { - if ((key->level == 2) && (*sigLen < DILITHIUM_LEVEL2_SIG_SIZE)) { + if ((key->level == WC_ML_DSA_44) && + (*sigLen < DILITHIUM_LEVEL2_SIG_SIZE)) { *sigLen = DILITHIUM_LEVEL2_SIG_SIZE; ret = BUFFER_E; } - else if ((key->level == 3) && (*sigLen < DILITHIUM_LEVEL3_SIG_SIZE)) { + else if ((key->level == WC_ML_DSA_65) && + (*sigLen < DILITHIUM_LEVEL3_SIG_SIZE)) { *sigLen = DILITHIUM_LEVEL3_SIG_SIZE; ret = BUFFER_E; } - else if ((key->level == 5) && (*sigLen < DILITHIUM_LEVEL5_SIG_SIZE)) { + else if ((key->level == WC_ML_DSA_87) && + (*sigLen < DILITHIUM_LEVEL5_SIG_SIZE)) { *sigLen = DILITHIUM_LEVEL5_SIG_SIZE; ret = BUFFER_E; } @@ -6659,13 +7172,13 @@ static int oqs_dilithium_verify_msg(const byte* sig, word32 sigLen, } if (ret == 0) { - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_44_ipd); } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_65_ipd); } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_87_ipd); } else { @@ -6980,7 +7493,7 @@ int wc_dilithium_init_id(dilithium_key* key, const unsigned char* id, int len, } /* Set the maximum level here */ - wc_dilithium_set_level(key, 5); + wc_dilithium_set_level(key, WC_ML_DSA_87); return ret; } @@ -7010,7 +7523,7 @@ int wc_dilithium_init_label(dilithium_key* key, const char* label, void* heap, } /* Set the maximum level here */ - wc_dilithium_set_level(key, 5); + wc_dilithium_set_level(key, WC_ML_DSA_87); return ret; } @@ -7030,7 +7543,8 @@ int wc_dilithium_set_level(dilithium_key* key, byte level) if (key == NULL) { ret = BAD_FUNC_ARG; } - if ((ret == 0) && (level != 2) && (level != 3) && (level != 5)) { + if ((ret == 0) && (level != WC_ML_DSA_44) && (level != WC_ML_DSA_65) && + (level != WC_ML_DSA_87)) { ret = BAD_FUNC_ARG; } @@ -7085,8 +7599,8 @@ int wc_dilithium_get_level(dilithium_key* key, byte* level) if ((key == NULL) || (level == NULL)) { ret = BAD_FUNC_ARG; } - if ((ret == 0) && (key->level != 2) && (key->level != 3) && - (key->level != 5)) { + if ((ret == 0) && (key->level != WC_ML_DSA_44) && + (key->level != WC_ML_DSA_65) && (key->level != WC_ML_DSA_87)) { ret = BAD_FUNC_ARG; } @@ -7138,13 +7652,13 @@ int wc_dilithium_size(dilithium_key* key) int ret = BAD_FUNC_ARG; if (key != NULL) { - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { ret = DILITHIUM_LEVEL2_KEY_SIZE; } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { ret = DILITHIUM_LEVEL3_KEY_SIZE; } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { ret = DILITHIUM_LEVEL5_KEY_SIZE; } } @@ -7164,13 +7678,13 @@ int wc_dilithium_priv_size(dilithium_key* key) int ret = BAD_FUNC_ARG; if (key != NULL) { - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { ret = DILITHIUM_LEVEL2_PRV_KEY_SIZE; } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { ret = DILITHIUM_LEVEL3_PRV_KEY_SIZE; } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { ret = DILITHIUM_LEVEL5_PRV_KEY_SIZE; } } @@ -7211,13 +7725,13 @@ int wc_dilithium_pub_size(dilithium_key* key) int ret = BAD_FUNC_ARG; if (key != NULL) { - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { ret = DILITHIUM_LEVEL2_PUB_KEY_SIZE; } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { ret = DILITHIUM_LEVEL3_PUB_KEY_SIZE; } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { ret = DILITHIUM_LEVEL5_PUB_KEY_SIZE; } } @@ -7257,13 +7771,13 @@ int wc_dilithium_sig_size(dilithium_key* key) int ret = BAD_FUNC_ARG; if (key != NULL) { - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { ret = DILITHIUM_LEVEL2_SIG_SIZE; } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { ret = DILITHIUM_LEVEL3_SIG_SIZE; } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { ret = DILITHIUM_LEVEL5_SIG_SIZE; } } @@ -7367,7 +7881,7 @@ int wc_dilithium_check_key(dilithium_key* key) const byte* pub_seed = key->p; ret = dilithium_expand_a(&key->shake, pub_seed, params->k, - params->l, a); + params->l, a, key->heap); #ifdef WC_DILITHIUM_CACHE_MATRIX_A key->aSet = (ret == 0); #endif @@ -7478,7 +7992,7 @@ int wc_dilithium_export_public(dilithium_key* key, byte* out, word32* outLen) if (ret == 0) { /* Get length passed in for checking. */ inLen = *outLen; - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { /* Set out length. */ *outLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE; /* Validate length passed in. */ @@ -7486,7 +8000,7 @@ int wc_dilithium_export_public(dilithium_key* key, byte* out, word32* outLen) ret = BUFFER_E; } } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { /* Set out length. */ *outLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE; /* Validate length passed in. */ @@ -7494,7 +8008,7 @@ int wc_dilithium_export_public(dilithium_key* key, byte* out, word32* outLen) ret = BUFFER_E; } } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { /* Set out length. */ *outLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE; /* Validate length passed in. */ @@ -7540,19 +8054,19 @@ int wc_dilithium_import_public(const byte* in, word32 inLen, dilithium_key* key) ret = BAD_FUNC_ARG; } if (ret == 0) { - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { /* Check length. */ if (inLen != DILITHIUM_LEVEL2_PUB_KEY_SIZE) { ret = BAD_FUNC_ARG; } } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { /* Check length. */ if (inLen != DILITHIUM_LEVEL3_PUB_KEY_SIZE) { ret = BAD_FUNC_ARG; } } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { /* Check length. */ if (inLen != DILITHIUM_LEVEL5_PUB_KEY_SIZE) { ret = BAD_FUNC_ARG; @@ -7603,7 +8117,7 @@ int wc_dilithium_import_public(const byte* in, word32 inLen, dilithium_key* key) if (ret == 0) { /* Compute matrix a from public key data. */ ret = dilithium_expand_a(&key->shake, key->p, key->params->k, - key->params->l, key->a); + key->params->l, key->a, key->heap); if (ret == 0) { key->aSet = 1; } @@ -7672,7 +8186,7 @@ static int dilithium_set_priv_key(const byte* priv, word32 privSz, if (ret == 0) { /* Compute matrix a from private key data. */ ret = dilithium_expand_a(&key->shake, key->k, params->k, params->l, - key->a); + key->a, key->heap); if (ret == 0) { key->aSet = 1; } @@ -7725,8 +8239,8 @@ int wc_dilithium_import_private(const byte* priv, word32 privSz, if ((priv == NULL) || (key == NULL)) { ret = BAD_FUNC_ARG; } - if ((ret == 0) && (key->level != 2) && (key->level != 3) && - (key->level != 5)) { + if ((ret == 0) && (key->level != WC_ML_DSA_44) && + (key->level != WC_ML_DSA_65) && (key->level != WC_ML_DSA_87)) { ret = BAD_FUNC_ARG; } @@ -7762,8 +8276,8 @@ int wc_dilithium_import_key(const byte* priv, word32 privSz, if ((pub == NULL) && (pubSz != 0)) { ret = BAD_FUNC_ARG; } - if ((ret == 0) && (key->level != 2) && (key->level != 3) && - (key->level != 5)) { + if ((ret == 0) && (key->level != WC_ML_DSA_44) && + (key->level != WC_ML_DSA_65) && (key->level != WC_ML_DSA_87)) { ret = BAD_FUNC_ARG; } @@ -7808,13 +8322,13 @@ int wc_dilithium_export_private(dilithium_key* key, byte* out, if (ret == 0) { inLen = *outLen; /* check and set up out length */ - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { *outLen = DILITHIUM_LEVEL2_KEY_SIZE; } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { *outLen = DILITHIUM_LEVEL3_KEY_SIZE; } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { *outLen = DILITHIUM_LEVEL5_KEY_SIZE; } else { @@ -7901,13 +8415,13 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, if (ret == 0) { /* Get OID sum for level. */ - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { keytype = DILITHIUM_LEVEL2k; } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { keytype = DILITHIUM_LEVEL3k; } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { keytype = DILITHIUM_LEVEL5k; } else { @@ -7923,19 +8437,19 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, } if ((ret == 0) && (pubKey == NULL) && (pubKeyLen == 0)) { /* Check if the public key is included in the private key. */ - if ((key->level == 2) && + if ((key->level == WC_ML_DSA_44) && (privKeyLen == DILITHIUM_LEVEL2_PRV_KEY_SIZE)) { pubKey = privKey + DILITHIUM_LEVEL2_KEY_SIZE; pubKeyLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE; privKeyLen -= DILITHIUM_LEVEL2_PUB_KEY_SIZE; } - else if ((key->level == 3) && + else if ((key->level == WC_ML_DSA_65) && (privKeyLen == DILITHIUM_LEVEL3_PRV_KEY_SIZE)) { pubKey = privKey + DILITHIUM_LEVEL3_KEY_SIZE; pubKeyLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE; privKeyLen -= DILITHIUM_LEVEL3_PUB_KEY_SIZE; } - else if ((key->level == 5) && + else if ((key->level == WC_ML_DSA_87) && (privKeyLen == DILITHIUM_LEVEL5_PRV_KEY_SIZE)) { pubKey = privKey + DILITHIUM_LEVEL5_KEY_SIZE; pubKeyLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE; @@ -7969,8 +8483,103 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, #endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */ +#endif /* WOLFSSL_DILITHIUM_NO_ASN1 */ + #ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY +#if defined(WOLFSSL_DILITHIUM_NO_ASN1) +#ifndef WOLFSSL_NO_ML_DSA_44 +static unsigned char dilithium_oid_44[] = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0b, + 0x0c, 0x04, 0x04 +}; +#endif +#ifndef WOLFSSL_NO_ML_DSA_65 +static unsigned char dilithium_oid_65[] = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0b, + 0x0c, 0x06, 0x05 +}; +#endif +#ifndef WOLFSSL_NO_ML_DSA_87 +static unsigned char dilithium_oid_87[] = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0b, + 0x0c, 0x08, 0x07 +}; +#endif + +static int dilitihium_get_der_length(const byte* input, word32* inOutIdx, + int *length, word32 inSz) +{ + int ret = 0; + word32 idx = *inOutIdx; + word32 len = 0; + + if (idx >= inSz) { + ret = ASN_PARSE_E; + } + else if (input[idx] < 0x80) { + len = input[idx]; + idx++; + } + else if ((input[idx] == 0x80) || (input[idx] >= 0x83)) { + ret = ASN_PARSE_E; + } + else if (input[idx] == 0x81) { + if (idx + 1 >= inSz) { + ret = ASN_PARSE_E; + } + else if (input[idx + 1] < 0x80) { + ret = ASN_PARSE_E; + } + else { + len = input[idx + 1]; + idx += 2; + } + } + else if (input[idx] == 0x82) { + if (idx + 2 >= inSz) { + ret = ASN_PARSE_E; + } + else { + len = ((word16)input[idx + 1] << 8) + input[idx + 2]; + idx += 3; + if (len < 0x100) { + ret = ASN_PARSE_E; + } + } + } + + if ((ret == 0) && ((idx + len) > inSz)) { + ret = ASN_PARSE_E; + } + + *length = (int)len; + *inOutIdx = idx; + return ret; +} + +static int dilithium_check_type(const byte* input, word32* inOutIdx, byte type, + word32 inSz) +{ + int ret = 0; + word32 idx = *inOutIdx; + + if (idx >= inSz) { + ret = ASN_PARSE_E; + } + else if (input[idx] != type){ + ret = ASN_PARSE_E; + } + else { + idx++; + } + + *inOutIdx = idx; + return ret; +} + +#endif /* WOLFSSL_DILITHIUM_NO_ASN1 */ + /* Decode the DER encoded Dilithium public key. * * @param [in] input Array holding DER encoded data. @@ -7989,7 +8598,6 @@ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, int ret = 0; const byte* pubKey; word32 pubKeyLen = 0; - int keytype = 0; /* Validate parameters. */ if ((input == NULL) || (inOutIdx == NULL) || (key == NULL) || (inSz == 0)) { @@ -8000,17 +8608,27 @@ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, /* Try to import the key directly. */ ret = wc_dilithium_import_public(input, inSz, key); if (ret != 0) { + #if !defined(WOLFSSL_DILITHIUM_NO_ASN1) + int keytype = 0; + #else + int length; + unsigned char* oid; + int oidLen; + word32 idx = 0; + #endif + /* Start again. */ ret = 0; + #if !defined(WOLFSSL_DILITHIUM_NO_ASN1) /* Get OID sum for level. */ - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { keytype = DILITHIUM_LEVEL2k; } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { keytype = DILITHIUM_LEVEL3k; } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { keytype = DILITHIUM_LEVEL5k; } else { @@ -8022,6 +8640,77 @@ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, ret = DecodeAsymKeyPublic_Assign(input, inOutIdx, inSz, &pubKey, &pubKeyLen, keytype); } + #else + /* Get OID sum for level. */ + #ifndef WOLFSSL_NO_ML_DSA_44 + if (key->level == WC_ML_DSA_44) { + oid = dilithium_oid_44; + oidLen = (int)sizeof(dilithium_oid_44); + } + else + #endif + #ifndef WOLFSSL_NO_ML_DSA_65 + if (key->level == WC_ML_DSA_65) { + oid = dilithium_oid_65; + oidLen = (int)sizeof(dilithium_oid_65); + } + else + #endif + #ifndef WOLFSSL_NO_ML_DSA_87 + if (key->level == WC_ML_DSA_87) { + oid = dilithium_oid_87; + oidLen = (int)sizeof(dilithium_oid_87); + } + else + #endif + { + /* Level not set. */ + ret = BAD_FUNC_ARG; + } + if (ret == 0) { + ret = dilithium_check_type(input, &idx, 0x30, inSz); + } + if (ret == 0) { + ret = dilitihium_get_der_length(input, &idx, &length, inSz); + } + if (ret == 0) { + ret = dilithium_check_type(input, &idx, 0x30, inSz); + } + if (ret == 0) { + ret = dilitihium_get_der_length(input, &idx, &length, inSz); + } + if (ret == 0) { + ret = dilithium_check_type(input, &idx, 0x06, inSz); + } + if (ret == 0) { + ret = dilitihium_get_der_length(input, &idx, &length, inSz); + } + if (ret == 0) { + if ((length != oidLen) || + (XMEMCMP(input + idx, oid, oidLen) != 0)) { + ret = ASN_PARSE_E; + } + idx += oidLen; + } + if (ret == 0) { + ret = dilithium_check_type(input, &idx, 0x03, inSz); + } + if (ret == 0) { + ret = dilitihium_get_der_length(input, &idx, &length, inSz); + } + if (ret == 0) { + if (input[idx] != 0) { + ret = ASN_PARSE_E; + } + idx++; + length--; + } + if (ret == 0) { + /* This is the raw point data compressed or uncompressed. */ + pubKeyLen = (word32)length; + pubKey = input + idx; + } + #endif if (ret == 0) { /* Import public key data. */ ret = wc_dilithium_import_public(pubKey, pubKeyLen, key); @@ -8031,6 +8720,8 @@ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, return ret; } +#ifndef WOLFSSL_DILITHIUM_NO_ASN1 + #ifdef WC_ENABLE_ASYM_KEY_EXPORT /* Encode the public part of a Dilithium key in DER. * @@ -8062,15 +8753,15 @@ int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, word32 len, if (ret == 0) { /* Get OID and length for level. */ - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { keytype = DILITHIUM_LEVEL2k; pubKeyLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE; } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { keytype = DILITHIUM_LEVEL3k; pubKeyLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE; } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { keytype = DILITHIUM_LEVEL5k; pubKeyLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE; } @@ -8089,10 +8780,14 @@ int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, word32 len, } #endif /* WC_ENABLE_ASYM_KEY_EXPORT */ +#endif /* !WOLFSSL_DILITHIUM_NO_ASN1 */ + #endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY */ #ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY +#ifndef WOLFSSL_DILITHIUM_NO_ASN1 + #ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY /* Encode the private and public data of a Dilithium key in DER. * @@ -8112,15 +8807,15 @@ int wc_Dilithium_KeyToDer(dilithium_key* key, byte* output, word32 len) /* Validate parameters and check public and private key set. */ if ((key != NULL) && key->prvKeySet && key->pubKeySet) { /* Create DER for level. */ - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, key->p, DILITHIUM_LEVEL2_PUB_KEY_SIZE, output, len, DILITHIUM_LEVEL2k); } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, key->p, DILITHIUM_LEVEL3_PUB_KEY_SIZE, output, len, DILITHIUM_LEVEL3k); } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, key->p, DILITHIUM_LEVEL5_PUB_KEY_SIZE, output, len, DILITHIUM_LEVEL5k); } @@ -8148,15 +8843,15 @@ int wc_Dilithium_PrivateKeyToDer(dilithium_key* key, byte* output, word32 len) /* Validate parameters and check private key set. */ if ((key != NULL) && key->prvKeySet) { /* Create DER for level. */ - if (key->level == 2) { + if (key->level == WC_ML_DSA_44) { ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, NULL, 0, output, len, DILITHIUM_LEVEL2k); } - else if (key->level == 3) { + else if (key->level == WC_ML_DSA_65) { ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, NULL, 0, output, len, DILITHIUM_LEVEL3k); } - else if (key->level == 5) { + else if (key->level == WC_ML_DSA_87) { ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, NULL, 0, output, len, DILITHIUM_LEVEL5k); } @@ -8165,8 +8860,8 @@ int wc_Dilithium_PrivateKeyToDer(dilithium_key* key, byte* output, word32 len) return ret; } -#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */ - #endif /* WOLFSSL_DILITHIUM_NO_ASN1 */ +#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */ + #endif /* HAVE_DILITHIUM */ diff --git a/wolfssl/wolfcrypt/dilithium.h b/wolfssl/wolfcrypt/dilithium.h index f82682f06..742c8ecb9 100644 --- a/wolfssl/wolfcrypt/dilithium.h +++ b/wolfssl/wolfcrypt/dilithium.h @@ -602,6 +602,9 @@ struct dilithium_key { sword32 w[DILITHIUM_N]; sword32 t1[DILITHIUM_N]; byte w1e[DILITHIUM_MAX_W1_ENC_SZ]; +#ifdef WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 + sword64 t64[DILITHIUM_N]; +#endif byte h[DILITHIUM_REJ_NTT_POLY_H_SIZE]; byte block[DILITHIUM_GEN_C_BLOCK_BYTES]; #endif /* WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC && @@ -712,11 +715,13 @@ int wc_dilithium_export_key(dilithium_key* key, byte* priv, word32 *privSz, WOLFSSL_API int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, dilithium_key* key, word32 inSz); #endif +#endif /* WOLFSSL_DILITHIUM_NO_ASN1 */ #ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY WOLFSSL_API int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, dilithium_key* key, word32 inSz); #endif +#ifndef WOLFSSL_DILITHIUM_NO_ASN1 #ifdef WC_ENABLE_ASYM_KEY_EXPORT WOLFSSL_API int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, word32 inLen, int withAlg);