diff options
Diffstat (limited to 'security/nss/cmd/fipstest/fipstest.c')
-rw-r--r-- | security/nss/cmd/fipstest/fipstest.c | 4851 |
1 files changed, 3397 insertions, 1454 deletions
diff --git a/security/nss/cmd/fipstest/fipstest.c b/security/nss/cmd/fipstest/fipstest.c index bea7f2e72..b683cd8ee 100644 --- a/security/nss/cmd/fipstest/fipstest.c +++ b/security/nss/cmd/fipstest/fipstest.c @@ -41,298 +41,39 @@ #include "secitem.h" #include "blapi.h" #include "nss.h" +#include "secerr.h" +#include "secder.h" +#include "secdig.h" +#include "keythi.h" +#include "ec.h" +#include "hasht.h" +#include "lowkeyi.h" +#include "softoken.h" +#include "pqgutil.h" + #if 0 #include "../../lib/freebl/mpi/mpi.h" #endif -static const unsigned char -table3[32][8] = { - { 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31 }, - { 0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20 }, - { 0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20 }, - { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20 }, - { 0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01 }, - { 0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01 }, - { 0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01 }, - { 0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01 }, - { 0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01 }, - { 0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01 }, - { 0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40 }, - { 0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40 }, - { 0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01 }, - { 0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01 }, - { 0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01 }, - { 0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20 }, - { 0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01 }, - { 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01 }, - { 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01 }, - { 0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01 }, - { 0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01 }, - { 0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01 }, - { 0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01 }, - { 0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01 }, - { 0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b }, - { 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01 }, - { 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02 }, - { 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08 }, - { 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04 }, - { 0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04 }, - { 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01 }, - { 0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01 } -}; - -static const unsigned char -table4_key[19][8] = { - { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 }, - { 0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e }, - { 0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86 }, - { 0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e }, - { 0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6 }, - { 0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce }, - { 0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6 }, - { 0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe }, - { 0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16 }, - { 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f }, - { 0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46 }, - { 0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e }, - { 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76 }, - { 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07 }, - { 0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f }, - { 0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7 }, - { 0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf }, - { 0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6 }, - { 0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef } -}; - -static const unsigned char -table4_inp[19][8] = { - { 0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42 }, - { 0x5c, 0xd5, 0x4c, 0xa8, 0x3d, 0xef, 0x57, 0xda }, - { 0x02, 0x48, 0xd4, 0x38, 0x06, 0xf6, 0x71, 0x72 }, - { 0x51, 0x45, 0x4b, 0x58, 0x2d, 0xdf, 0x44, 0x0a }, - { 0x42, 0xfd, 0x44, 0x30, 0x59, 0x57, 0x7f, 0xa2 }, - { 0x05, 0x9b, 0x5e, 0x08, 0x51, 0xcf, 0x14, 0x3a }, - { 0x07, 0x56, 0xd8, 0xe0, 0x77, 0x47, 0x61, 0xd2 }, - { 0x76, 0x25, 0x14, 0xb8, 0x29, 0xbf, 0x48, 0x6a }, - { 0x3b, 0xdd, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02 }, - { 0x26, 0x95, 0x5f, 0x68, 0x35, 0xaf, 0x60, 0x9a }, - { 0x16, 0x4d, 0x5e, 0x40, 0x4f, 0x27, 0x52, 0x32 }, - { 0x6b, 0x05, 0x6e, 0x18, 0x75, 0x9f, 0x5c, 0xca }, - { 0x00, 0x4b, 0xd6, 0xef, 0x09, 0x17, 0x60, 0x62 }, - { 0x48, 0x0d, 0x39, 0x00, 0x6e, 0xe7, 0x62, 0xf2 }, - { 0x43, 0x75, 0x40, 0xc8, 0x69, 0x8f, 0x3c, 0xfa }, - { 0x07, 0x2d, 0x43, 0xa0, 0x77, 0x07, 0x52, 0x92 }, - { 0x02, 0xfe, 0x55, 0x77, 0x81, 0x17, 0xf1, 0x2a }, - { 0x1d, 0x9d, 0x5c, 0x50, 0x18, 0xf7, 0x28, 0xc2 }, - { 0x30, 0x55, 0x32, 0x28, 0x6d, 0x6f, 0x29, 0x5a } -}; +#ifdef NSS_ENABLE_ECC +extern SECStatus +EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams); +extern SECStatus +EC_CopyParams(PRArenaPool *arena, ECParams *dstParams, + const ECParams *srcParams); +#endif -static const unsigned char -des_ecb_enc_sample_key[8] = { 0x97, 0xae, 0x43, 0x08, 0xb6, 0xa8, 0x7a, 0x08 }; -static const unsigned char -des_ecb_enc_sample_inp[8] = { 0xcf, 0xcd, 0x91, 0xf1, 0xb3, 0x40, 0xc9, 0x91 }; - -static const unsigned char -des_ecb_dec_sample_key[8] = { 0x0b, 0x8c, 0x38, 0xef, 0x52, 0x01, 0xda, 0x13 }; -static const unsigned char -des_ecb_dec_sample_inp[8] = { 0x58, 0x0b, 0x39, 0x57, 0x3d, 0x9b, 0x8d, 0xdf }; - -static const unsigned char -des_cbc_enc_sample_key[8] = { 0x58, 0x62, 0xd3, 0xf8, 0x04, 0xe9, 0xb3, 0x98 }; -static const unsigned char -des_cbc_enc_sample_iv[8] = { 0xac, 0xcf, 0x45, 0x4c, 0x1a, 0x28, 0x68, 0xcf }; -static const unsigned char -des_cbc_enc_sample_inp[8] = { 0xf1, 0x55, 0x47, 0x63, 0x76, 0x0e, 0x43, 0xa9 }; - -static const unsigned char -des_cbc_dec_sample_key[8] = { 0x64, 0x6d, 0x02, 0x75, 0xe9, 0x34, 0xe6, 0x7a }; -static const unsigned char -des_cbc_dec_sample_iv[8] = { 0xb4, 0x32, 0xa3, 0x8c, 0xd5, 0xe3, 0x20, 0x1a }; -static const unsigned char -des_cbc_dec_sample_inp[8] = { 0x5a, 0xfe, 0xe8, 0xf2, 0xf6, 0x63, 0x4f, 0xb6 }; - -static const unsigned char -tdea_ecb_enc_sample_key[24] = { - 0x0b, 0x62, 0x7f, 0x67, 0xea, 0xda, 0x0b, 0x34, - 0x08, 0x07, 0x3b, 0xc8, 0x8c, 0x23, 0x1a, 0xb6, - 0x75, 0x0b, 0x9e, 0x57, 0x83, 0xf4, 0xe6, 0xa4 }; -static const unsigned char -tdea_ecb_enc_sample_inp[8] = { 0x44, 0x15, 0x7a, 0xb0, 0x0a, 0x78, 0x6d, 0xbf }; - -static const unsigned char -tdea_ecb_dec_sample_key[24] = { - 0x91, 0xe5, 0x07, 0xba, 0x01, 0x01, 0xb6, 0xdc, - 0x0e, 0x51, 0xf1, 0xd0, 0x25, 0xc2, 0xc2, 0x1c, - 0x1f, 0x54, 0x2f, 0xa1, 0xf8, 0xce, 0xda, 0x89 }; -static const unsigned char -tdea_ecb_dec_sample_inp[8] = { 0x66, 0xe8, 0x72, 0x0d, 0x42, 0x85, 0x4b, 0xba }; - -static const unsigned char -tdea_cbc_enc_sample_key[24] = { - 0xd5, 0xe5, 0x61, 0x61, 0xb0, 0xc4, 0xa4, 0x25, - 0x45, 0x1a, 0x15, 0x67, 0xa4, 0x89, 0x6b, 0xc4, - 0x3b, 0x54, 0x1a, 0x4c, 0x1a, 0xb5, 0x49, 0x0d }; -static const unsigned char -tdea_cbc_enc_sample_iv[8] = { 0x5a, 0xb2, 0xa7, 0x3e, 0xc4, 0x3c, 0xe7, 0x1e }; -static const unsigned char -tdea_cbc_enc_sample_inp[8] = { 0x9e, 0x76, 0x87, 0x7c, 0x54, 0x14, 0xab, 0x50 }; - -static const unsigned char -tdea_cbc_dec_sample_key[24] = { - 0xf8, 0x25, 0xcd, 0x02, 0xc7, 0x76, 0xe6, 0xce, - 0x9e, 0x16, 0xe6, 0x40, 0x7f, 0xcd, 0x01, 0x80, - 0x5b, 0x38, 0xc4, 0xe0, 0xb5, 0x6e, 0x94, 0x61 }; -static const unsigned char -tdea_cbc_dec_sample_iv[8] = { 0x74, 0x3e, 0xdc, 0xc2, 0xc6, 0xc4, 0x18, 0xe3 }; -static const unsigned char -tdea_cbc_dec_sample_inp[8] = { 0xbe, 0x47, 0xd1, 0x77, 0xa5, 0xe8, 0x29, 0xfb }; - - -static const unsigned char -des_ecb_enc_key[8] = { 0x49, 0x45, 0xd9, 0x3d, 0x83, 0xcd, 0x61, 0x9b }; -static const unsigned char -des_ecb_enc_inp[8] = { 0x81, 0xf2, 0x12, 0x0d, 0x99, 0x04, 0x5d, 0x16 }; - -static const unsigned char -des_ecb_dec_key[8] = { 0x7a, 0x6b, 0x61, 0x76, 0xc8, 0x85, 0x43, 0x31 }; -static const unsigned char -des_ecb_dec_inp[8] = { 0xef, 0xe4, 0x6e, 0x4f, 0x4f, 0xc3, 0x28, 0xcc }; - -static const unsigned char -des_cbc_enc_key[8] = { 0xc8, 0x5e, 0xfd, 0xa7, 0xa7, 0xc2, 0xc4, 0x0d }; -static const unsigned char -des_cbc_enc_iv[8] = { 0x4c, 0xb9, 0xcf, 0x46, 0xff, 0x7a, 0x3d, 0xff }; -static const unsigned char -des_cbc_enc_inp[8] = { 0x80, 0x1b, 0x24, 0x9b, 0x24, 0x0e, 0xa5, 0x96 }; - -static const unsigned char -des_cbc_dec_key[8] = { 0x2c, 0x3d, 0xa1, 0x67, 0x4c, 0xfb, 0x85, 0x23 }; -static const unsigned char -des_cbc_dec_iv[8] = { 0x7a, 0x0a, 0xc2, 0x15, 0x1d, 0x22, 0x98, 0x3a }; -static const unsigned char -des_cbc_dec_inp[8] = { 0x2d, 0x5d, 0x02, 0x04, 0x98, 0x5d, 0x5e, 0x28 }; - -static const unsigned char -tdea1_ecb_enc_key[24] = { - 0x89, 0xcd, 0xd3, 0xf1, 0x01, 0xc1, 0x1a, 0xf4, - 0x89, 0xcd, 0xd3, 0xf1, 0x01, 0xc1, 0x1a, 0xf4, - 0x89, 0xcd, 0xd3, 0xf1, 0x01, 0xc1, 0x1a, 0xf4 }; - -static const unsigned char -tdea1_ecb_enc_inp[8] = { 0xe5, 0x8c, 0x48, 0xf0, 0x91, 0x4e, 0xeb, 0x87 }; - -static const unsigned char -tdea1_ecb_dec_key[24] = { - 0xbf, 0x86, 0x94, 0xe0, 0x83, 0x46, 0x70, 0x37, - 0xbf, 0x86, 0x94, 0xe0, 0x83, 0x46, 0x70, 0x37, - 0xbf, 0x86, 0x94, 0xe0, 0x83, 0x46, 0x70, 0x37 }; - -static const unsigned char -tdea1_ecb_dec_inp[8] = { 0x35, 0x7a, 0x6c, 0x05, 0xe0, 0x8c, 0x3d, 0xb7 }; - -static const unsigned char -tdea1_cbc_enc_key[24] = { - 0x46, 0xf1, 0x6d, 0xbf, 0xe3, 0xd5, 0xd3, 0x94, - 0x46, 0xf1, 0x6d, 0xbf, 0xe3, 0xd5, 0xd3, 0x94, - 0x46, 0xf1, 0x6d, 0xbf, 0xe3, 0xd5, 0xd3, 0x94 }; - - -static const unsigned char -tdea1_cbc_enc_iv[8] = { 0xf7, 0x3e, 0x14, 0x05, 0x88, 0xeb, 0x2e, 0x96 }; -static const unsigned char -tdea1_cbc_enc_inp[8] = { 0x18, 0x1b, 0xdf, 0x18, 0x10, 0xb2, 0xe0, 0x05 }; - -static const unsigned char -tdea1_cbc_dec_key[24] = { - 0x83, 0xd0, 0x54, 0xa2, 0x92, 0xe9, 0x6e, 0x7c, - 0x83, 0xd0, 0x54, 0xa2, 0x92, 0xe9, 0x6e, 0x7c, - 0x83, 0xd0, 0x54, 0xa2, 0x92, 0xe9, 0x6e, 0x7c }; - - -static const unsigned char -tdea1_cbc_dec_iv[8] = { 0xb9, 0x65, 0x4a, 0x94, 0xba, 0x6a, 0x66, 0xf9 }; -static const unsigned char -tdea1_cbc_dec_inp[8] = { 0xce, 0xb8, 0x30, 0x95, 0xac, 0x82, 0xdf, 0x9b }; - -static const unsigned char -tdea2_ecb_enc_key[24] = { - 0x79, 0x98, 0x4a, 0xe9, 0x23, 0xad, 0x10, 0xda, - 0x16, 0x3e, 0xb5, 0xfe, 0xcd, 0x52, 0x20, 0x01, - 0x79, 0x98, 0x4a, 0xe9, 0x23, 0xad, 0x10, 0xda }; -static const unsigned char -tdea2_ecb_enc_inp[8] = { 0x99, 0xd2, 0xca, 0xe8, 0xa7, 0x90, 0x13, 0xc2 }; - -static const unsigned char -tdea2_ecb_dec_key[24] = { - 0x98, 0xcd, 0x29, 0x52, 0x85, 0x91, 0x75, 0xe3, - 0xab, 0x29, 0xe3, 0x10, 0xa2, 0x10, 0x04, 0x58, - 0x98, 0xcd, 0x29, 0x52, 0x85, 0x91, 0x75, 0xe3 }; - -static const unsigned char -tdea2_ecb_dec_inp[8] = { 0xc0, 0x35, 0x24, 0x1f, 0xc9, 0x29, 0x5c, 0x7a }; - -static const unsigned char -tdea2_cbc_enc_key[24] = { - 0xba, 0x5d, 0x70, 0xf8, 0x08, 0x13, 0xb0, 0x4c, - 0xf8, 0x46, 0xa8, 0xce, 0xe6, 0xb3, 0x08, 0x02, - 0xba, 0x5d, 0x70, 0xf8, 0x08, 0x13, 0xb0, 0x4c }; - - -static const unsigned char -tdea2_cbc_enc_iv[8] = { 0xe8, 0x39, 0xd7, 0x3a, 0x8d, 0x8c, 0x59, 0x8a }; -static const unsigned char -tdea2_cbc_enc_inp[8] = { 0x6e, 0x85, 0x0a, 0x4c, 0x86, 0x86, 0x70, 0x23 }; - -static const unsigned char -tdea2_cbc_dec_key[24] = { - 0x25, 0xf8, 0x9e, 0x7a, 0xef, 0x26, 0xb5, 0x9e, - 0x46, 0x32, 0x19, 0x9b, 0xea, 0x1c, 0x19, 0xad, - 0x25, 0xf8, 0x9e, 0x7a, 0xef, 0x26, 0xb5, 0x9e }; - - -static const unsigned char -tdea2_cbc_dec_iv[8] = { 0x48, 0x07, 0x6f, 0xf9, 0x05, 0x14, 0xc1, 0xdc }; -static const unsigned char -tdea2_cbc_dec_inp[8] = { 0x9e, 0xf4, 0x10, 0x55, 0xe8, 0x7e, 0x7e, 0x25 }; - -static const unsigned char -tdea3_ecb_enc_key[24] = { - 0x6d, 0x37, 0x16, 0x31, 0x6e, 0x02, 0x83, 0xb6, - 0xf7, 0x16, 0xa2, 0x64, 0x57, 0x8c, 0xae, 0x34, - 0xd0, 0xce, 0x38, 0xb6, 0x31, 0x5e, 0xae, 0x1a }; -static const unsigned char -tdea3_ecb_enc_inp[8] = { 0x28, 0x8a, 0x45, 0x22, 0x53, 0x95, 0xba, 0x3c }; - -static const unsigned char -tdea3_ecb_dec_key[24] = { - 0xb0, 0x75, 0x92, 0x2c, 0xfd, 0x67, 0x8a, 0x26, - 0xc8, 0xba, 0xad, 0x68, 0xb6, 0xba, 0x92, 0x49, - 0xe3, 0x2c, 0xec, 0x83, 0x34, 0xe6, 0xda, 0x98 }; -static const unsigned char -tdea3_ecb_dec_inp[8] = { 0x03, 0xcc, 0xe6, 0x65, 0xf6, 0xc5, 0xc3, 0xba }; - -static const unsigned char -tdea3_cbc_enc_key[24] = { - 0x01, 0x32, 0x73, 0xe9, 0xcb, 0x8a, 0x89, 0x80, - 0x02, 0x7a, 0xc1, 0x5d, 0xf4, 0xd5, 0x6b, 0x76, - 0x2f, 0xef, 0xfd, 0x58, 0x57, 0x1a, 0xce, 0x29 }; -static const unsigned char -tdea3_cbc_enc_iv[8] = { 0x93, 0x98, 0x7c, 0x66, 0x98, 0x21, 0x5b, 0x9e }; -static const unsigned char -tdea3_cbc_enc_inp[8] = { 0x16, 0x54, 0x09, 0xd2, 0x2c, 0xad, 0x6d, 0x99 }; - -static const unsigned char -tdea3_cbc_dec_key[24] = { - 0x57, 0x70, 0x3b, 0x4f, 0xae, 0xe6, 0x9d, 0x0e, - 0x4c, 0x3b, 0x23, 0xcd, 0x54, 0x20, 0xbc, 0x58, - 0x3b, 0x8a, 0x4a, 0xf1, 0x73, 0xf8, 0xf8, 0x38 }; -static const unsigned char -tdea3_cbc_dec_iv[8] = { 0x5f, 0x62, 0xe4, 0xea, 0xa7, 0xb2, 0xb5, 0x70 }; -static const unsigned char -tdea3_cbc_dec_inp[8] = { 0x44, 0xb3, 0xe6, 0x3b, 0x1f, 0xbb, 0x43, 0x02 }; +#define ENCRYPT 1 +#define DECRYPT 0 +#define BYTE unsigned char +#define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001 +#define RSA_MAX_TEST_MODULUS_BITS 4096 +#define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8 +#define RSA_MAX_TEST_EXPONENT_BYTES 8 +#define PQG_TEST_SEED_BYTES 20 SECStatus -hex_from_2char(unsigned char *c2, unsigned char *byteval) +hex_from_2char(const char *c2, unsigned char *byteval) { int i; unsigned char offset; @@ -355,7 +96,7 @@ hex_from_2char(unsigned char *c2, unsigned char *byteval) } SECStatus -char2_from_hex(unsigned char byteval, unsigned char *c2, char a) +char2_from_hex(unsigned char byteval, char *c2, char a) { int i; unsigned char offset; @@ -381,463 +122,778 @@ to_hex_str(char *str, const unsigned char *buf, unsigned int len) } void -to_hex_str_cap(char *str, unsigned char *buf, unsigned int len) +to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len) { unsigned int i; for (i=0; i<len; i++) { char2_from_hex(buf[i], &str[2*i], 'A'); } + str[2*len] = '\0'; } -void -des_var_pt_kat(int mode, PRBool encrypt, unsigned int len, - unsigned char *key, unsigned char *iv, - unsigned char *inp) +/* + * Convert a string of hex digits (str) to an array (buf) of len bytes. + * Return PR_TRUE if the hex string can fit in the byte array. Return + * PR_FALSE if the hex string is empty or is too long. + */ +PRBool +from_hex_str(unsigned char *buf, unsigned int len, const char *str) { - int i; - unsigned int olen, mbnum = 0; - unsigned char mod_byte = 0x80; - unsigned char in[8]; - unsigned char out[8]; - char keystr[17], ivstr[17], instr[17], outstr[17]; - char *ptty = (len == 8) ? "PT" : "PLAINTEXT"; - char *ctty = (len == 8) ? "CT" : "CIPHERTEXT"; - char tchar = (len == 8) ? '\t' : '\n'; - DESContext *cx1 = NULL, *cx2 = NULL; - memset(in, 0, sizeof in); - memset(keystr, 0, sizeof keystr); - memset(ivstr, 0, sizeof ivstr); - memset(instr, 0, sizeof instr); - memset(outstr, 0, sizeof outstr); - in[mbnum] = mod_byte; - for (i=1; i<=64; i++) { - cx1 = DES_CreateContext(key, iv, mode, PR_TRUE); - if (!encrypt) { - cx2 = DES_CreateContext(key, iv, mode, PR_FALSE); - } - if (len > 8) { - printf("COUNT = %d\n", i); - to_hex_str(keystr, key, 8); - printf("KEY1=%s\n", keystr); - to_hex_str(keystr, key+8, 8); - printf("KEY2=%s\n", keystr); - to_hex_str(keystr, key+16, 8); - printf("KEY3=%s\n", keystr); - } else { - to_hex_str(keystr, key, 8); - printf("%ld\tKEY=%s\t", i, keystr); - } - if (iv) { - to_hex_str(ivstr, iv, 8); - printf("IV=%s%c", ivstr, tchar); - } - DES_Encrypt(cx1, out, &olen, 8, in, 8); - if (encrypt) { - to_hex_str(instr, in, 8); - to_hex_str(outstr, out, 8); - printf("%s=%s%c%s=%s\n\n", ptty, instr, tchar, ctty, outstr); - } else { - unsigned char inv[8]; - DES_Decrypt(cx2, inv, &olen, 8, out, 8); - to_hex_str(instr, out, 8); - to_hex_str(outstr, inv, 8); - printf("%s=%s%c%s=%s\n\n", ctty, instr, tchar, ptty, outstr); - } - if (mod_byte > 0x01) { - mod_byte >>= 1; - } else { - in[mbnum] = 0x00; - mod_byte = 0x80; - mbnum++; + unsigned int nxdigit; /* number of hex digits in str */ + unsigned int i; /* index into buf */ + unsigned int j; /* index into str */ + + /* count the hex digits */ + nxdigit = 0; + for (nxdigit = 0; isxdigit(str[nxdigit]); nxdigit++) { + /* empty body */ + } + if (nxdigit == 0) { + return PR_FALSE; + } + if (nxdigit > 2*len) { + /* + * The input hex string is too long, but we allow it if the + * extra digits are leading 0's. + */ + for (j = 0; j < nxdigit-2*len; j++) { + if (str[j] != '0') { + return PR_FALSE; + } } - in[mbnum] = mod_byte; - DES_DestroyContext(cx1, PR_TRUE); - if (cx2) { - DES_DestroyContext(cx2, PR_TRUE); + /* skip leading 0's */ + str += nxdigit-2*len; + nxdigit = 2*len; + } + for (i=0, j=0; i< len; i++) { + if (2*i < 2*len-nxdigit) { + /* Handle a short input as if we padded it with leading 0's. */ + if (2*i+1 < 2*len-nxdigit) { + buf[i] = 0; + } else { + char tmp[2]; + tmp[0] = '0'; + tmp[1] = str[j]; + hex_from_2char(tmp, &buf[i]); + j++; + } + } else { + hex_from_2char(&str[j], &buf[i]); + j += 2; } } + return PR_TRUE; } -void -des_inv_perm_kat(int mode, PRBool encrypt, unsigned int len, - unsigned char *key, unsigned char *iv, - unsigned char *inp) +SECStatus +tdea_encrypt_buf( + int mode, + const unsigned char *key, + const unsigned char *iv, + unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, + const unsigned char *input, unsigned int inputlen) { - int i; - unsigned int olen, mbnum = 0; - unsigned char mod_byte = 0x80; - unsigned char in[8]; - unsigned char out[8]; - char keystr[17], ivstr[17], instr[17], outstr[17]; - char *ptty = (len == 8) ? "PT" : "PLAINTEXT"; - char *ctty = (len == 8) ? "CT" : "CIPHERTEXT"; - char tchar = (len == 8) ? '\t' : '\n'; - DESContext *cx1 = NULL, *cx2 = NULL; - memset(in, 0, sizeof in); - memset(keystr, 0, sizeof keystr); - memset(ivstr, 0, sizeof ivstr); - memset(instr, 0, sizeof instr); - memset(outstr, 0, sizeof outstr); - in[mbnum] = mod_byte; - for (i=1; i<=64; i++) { - if (encrypt) { - cx1 = DES_CreateContext(key, iv, mode, PR_TRUE); - cx2 = DES_CreateContext(key, iv, mode, PR_TRUE); - } else { - cx1 = DES_CreateContext(key, iv, mode, PR_FALSE); - } - if (len > 8) { - printf("COUNT = %d\n", i); - to_hex_str(keystr, key, 8); - printf("KEY1=%s\n", keystr); - to_hex_str(keystr, key+8, 8); - printf("KEY2=%s\n", keystr); - to_hex_str(keystr, key+16, 8); - printf("KEY3=%s\n", keystr); - } else { - to_hex_str(keystr, key, 8); - printf("%ld\tKEY=%s\t", i, keystr); - } - if (iv) { - to_hex_str(ivstr, iv, 8); - printf("IV=%s%c", ivstr, tchar); - } - if (encrypt) { - unsigned char inv[8]; - DES_Encrypt(cx1, out, &olen, 8, in, 8); - DES_Encrypt(cx2, inv, &olen, 8, out, 8); - to_hex_str(instr, out, 8); - to_hex_str(outstr, inv, 8); - printf("%s=%s%c%s=%s\n\n", ptty, instr, tchar, ctty, outstr); - } else { - DES_Decrypt(cx1, out, &olen, 8, in, 8); - to_hex_str(instr, in, 8); - to_hex_str(outstr, out, 8); - printf("%s=%s%c%s=%s\n\n", ctty, instr, tchar, ptty, outstr); - } - if (mod_byte > 0x01) { - mod_byte >>= 1; - } else { - in[mbnum] = 0x00; - mod_byte = 0x80; - mbnum++; - } - in[mbnum] = mod_byte; - DES_DestroyContext(cx1, PR_TRUE); - if (cx2) { - DES_DestroyContext(cx2, PR_TRUE); - } + SECStatus rv = SECFailure; + DESContext *cx; + unsigned char doublecheck[8*20]; /* 1 to 20 blocks */ + unsigned int doublechecklen = 0; + + cx = DES_CreateContext(key, iv, mode, PR_TRUE); + if (cx == NULL) { + goto loser; + } + rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen); + if (rv != SECSuccess) { + goto loser; + } + if (*outputlen != inputlen) { + goto loser; + } + DES_DestroyContext(cx, PR_TRUE); + cx = NULL; + + /* + * Doublecheck our result by decrypting the ciphertext and + * compare the output with the input plaintext. + */ + cx = DES_CreateContext(key, iv, mode, PR_FALSE); + if (cx == NULL) { + goto loser; + } + rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck, + output, *outputlen); + if (rv != SECSuccess) { + goto loser; + } + if (doublechecklen != *outputlen) { + goto loser; + } + DES_DestroyContext(cx, PR_TRUE); + cx = NULL; + if (memcmp(doublecheck, input, inputlen) != 0) { + goto loser; + } + rv = SECSuccess; + +loser: + if (cx != NULL) { + DES_DestroyContext(cx, PR_TRUE); } + return rv; } -void -des_var_key_kat(int mode, PRBool encrypt, unsigned int len, - unsigned char *key, unsigned char *iv, - unsigned char *inp) +SECStatus +tdea_decrypt_buf( + int mode, + const unsigned char *key, + const unsigned char *iv, + unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, + const unsigned char *input, unsigned int inputlen) { - int i; - unsigned int olen, mbnum = 0; - unsigned char mod_byte = 0x80; - unsigned char keyin[24]; - unsigned char out[8]; - char keystr[17], ivstr[17], instr[17], outstr[17]; - char *ptty = (len == 8) ? "PT" : "PLAINTEXT"; - char *ctty = (len == 8) ? "CT" : "CIPHERTEXT"; - char tchar = (len == 8) ? '\t' : '\n'; - DESContext *cx1 = NULL, *cx2 = NULL; - memset(keyin, 1, sizeof keyin); - memset(keystr, 0, sizeof keystr); - memset(ivstr, 0, sizeof ivstr); - memset(instr, 0, sizeof instr); - memset(outstr, 0, sizeof outstr); - keyin[mbnum] = mod_byte; - keyin[mbnum+8] = mod_byte; - keyin[mbnum+16] = mod_byte; - for (i=1; i<=56; i++) { - cx1 = DES_CreateContext(keyin, iv, mode, PR_TRUE); - if (!encrypt) { - cx2 = DES_CreateContext(keyin, iv, mode, PR_FALSE); - } - if (len > 8) { - printf("COUNT = %d\n", i); - to_hex_str(keystr, keyin, 8); - printf("KEY1=%s\n", keystr); - to_hex_str(keystr, keyin+8, 8); - printf("KEY2=%s\n", keystr); - to_hex_str(keystr, keyin+16, 8); - printf("KEY3=%s\n", keystr); - } else { - to_hex_str(keystr, keyin, 8); - printf("%ld\tKEY=%s\t", i, keystr); - } - if (iv) { - to_hex_str(ivstr, iv, 8); - printf("IV=%s%c", ivstr, tchar); - } - DES_Encrypt(cx1, out, &olen, 8, inp, 8); - if (encrypt) { - to_hex_str(instr, inp, 8); - to_hex_str(outstr, out, 8); - printf("%s=%s%c%s=%s\n\n", ptty, instr, tchar, ctty, outstr); - } else { - unsigned char inv[8]; - DES_Decrypt(cx2, inv, &olen, 8, out, 8); - to_hex_str(instr, out, 8); - to_hex_str(outstr, inv, 8); - printf("%s=%s%c%s=%s\n\n", ctty, instr, tchar, ptty, outstr); - } - if (mod_byte > 0x02) { - mod_byte >>= 1; - } else { - keyin[mbnum] = 0x01; - keyin[mbnum+8] = 0x01; - keyin[mbnum+16] = 0x01; - mod_byte = 0x80; - mbnum++; - } - keyin[mbnum] = mod_byte; - keyin[mbnum+8] = mod_byte; - keyin[mbnum+16] = mod_byte; - DES_DestroyContext(cx1, PR_TRUE); - if (cx2) { - DES_DestroyContext(cx2, PR_TRUE); - } + SECStatus rv = SECFailure; + DESContext *cx; + unsigned char doublecheck[8*20]; /* 1 to 20 blocks */ + unsigned int doublechecklen = 0; + + cx = DES_CreateContext(key, iv, mode, PR_FALSE); + if (cx == NULL) { + goto loser; + } + rv = DES_Decrypt(cx, output, outputlen, maxoutputlen, + input, inputlen); + if (rv != SECSuccess) { + goto loser; + } + if (*outputlen != inputlen) { + goto loser; + } + DES_DestroyContext(cx, PR_TRUE); + cx = NULL; + + /* + * Doublecheck our result by encrypting the plaintext and + * compare the output with the input ciphertext. + */ + cx = DES_CreateContext(key, iv, mode, PR_TRUE); + if (cx == NULL) { + goto loser; + } + rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck, + output, *outputlen); + if (rv != SECSuccess) { + goto loser; + } + if (doublechecklen != *outputlen) { + goto loser; + } + DES_DestroyContext(cx, PR_TRUE); + cx = NULL; + if (memcmp(doublecheck, input, inputlen) != 0) { + goto loser; + } + rv = SECSuccess; + +loser: + if (cx != NULL) { + DES_DestroyContext(cx, PR_TRUE); } + return rv; } +/* + * Perform the TDEA Known Answer Test (KAT) or Multi-block Message + * Test (MMT) in ECB or CBC mode. The KAT (there are five types) + * and MMT have the same structure: given the key and IV (CBC mode + * only), encrypt the given plaintext or decrypt the given ciphertext. + * So we can handle them the same way. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ void -des_perm_op_kat(int mode, PRBool encrypt, unsigned int len, - unsigned char *key, unsigned char *iv, - unsigned char *inp) +tdea_kat_mmt(char *reqfn) { - int i; - unsigned int olen; - unsigned char keyin[24]; - unsigned char out[8]; - char keystr[17], ivstr[17], instr[17], outstr[17]; - char *ptty = (len == 8) ? "PT" : "PLAINTEXT"; - char *ctty = (len == 8) ? "CT" : "CIPHERTEXT"; - char tchar = (len == 8) ? '\t' : '\n'; - DESContext *cx1 = NULL, *cx2 = NULL; - memset(keyin, 0, sizeof keyin); - memset(keystr, 0, sizeof keystr); - memset(ivstr, 0, sizeof ivstr); - memset(instr, 0, sizeof instr); - memset(outstr, 0, sizeof outstr); - for (i=0; i<32; i++) { - memcpy(keyin, table3[i], 8); - memcpy(keyin+8, table3[i], 8); - memcpy(keyin+16, table3[i], 8); - cx1 = DES_CreateContext(keyin, iv, mode, PR_TRUE); - if (!encrypt) { - cx2 = DES_CreateContext(keyin, iv, mode, PR_FALSE); - } - if (len > 8) { - printf("COUNT = %d\n", i); - to_hex_str(keystr, keyin, 8); - printf("KEY1=%s\n", keystr); - to_hex_str(keystr, keyin+8, 8); - printf("KEY2=%s\n", keystr); - to_hex_str(keystr, keyin+16, 8); - printf("KEY3=%s\n", keystr); - } else { - to_hex_str(keystr, keyin, 8); - printf("%ld\tKEY=%s\t", i, keystr); - } - if (iv) { - to_hex_str(ivstr, iv, 8); - printf("IV=%s%c", ivstr, tchar); - } - DES_Encrypt(cx1, out, &olen, 8, inp, 8); - if (encrypt) { - to_hex_str(instr, inp, 8); - to_hex_str(outstr, out, 8); - printf("%s=%s%c%s=%s\n\n", ptty, instr, tchar, ctty, outstr); - } else { - unsigned char inv[8]; - DES_Decrypt(cx2, inv, &olen, 8, out, 8); - to_hex_str(instr, out, 8); - to_hex_str(outstr, inv, 8); - printf("%s=%s%c%s=%s\n\n", ctty, instr, tchar, ptty, outstr); - } - DES_DestroyContext(cx1, PR_TRUE); - if (cx2) { - DES_DestroyContext(cx2, PR_TRUE); - } + char buf[180]; /* holds one line from the input REQUEST file. + * needs to be large enough to hold the longest + * line "CIPHERTEXT = <180 hex digits>\n". + */ + FILE *req; /* input stream from the REQUEST file */ + FILE *resp; /* output stream to the RESPONSE file */ + int i, j; + int mode; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */ + int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */ + unsigned char key[24]; /* TDEA 3 key bundle */ + unsigned int numKeys = 0; + unsigned char iv[8]; /* for all modes except ECB */ + unsigned char plaintext[8*20]; /* 1 to 20 blocks */ + unsigned int plaintextlen; + unsigned char ciphertext[8*20]; /* 1 to 20 blocks */ + unsigned int ciphertextlen; + SECStatus rv; + + req = fopen(reqfn, "r"); + resp = stdout; + while (fgets(buf, sizeof buf, req) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, resp); + continue; + } + /* [ENCRYPT] or [DECRYPT] */ + if (buf[0] == '[') { + if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { + crypt = ENCRYPT; + } else { + crypt = DECRYPT; + } + fputs(buf, resp); + continue; + } + /* NumKeys */ + if (strncmp(&buf[0], "NumKeys", 7) == 0) { + i = 7; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + numKeys = buf[i]; + fputs(buf, resp); + continue; + } + /* "COUNT = x" begins a new data set */ + if (strncmp(buf, "COUNT", 5) == 0) { + /* mode defaults to ECB, if dataset has IV mode will be set CBC */ + mode = NSS_DES_EDE3; + /* zeroize the variables for the test with this data set */ + memset(key, 0, sizeof key); + memset(iv, 0, sizeof iv); + memset(plaintext, 0, sizeof plaintext); + plaintextlen = 0; + memset(ciphertext, 0, sizeof ciphertext); + ciphertextlen = 0; + fputs(buf, resp); + continue; + } + if (numKeys == 0) { + if (strncmp(buf, "KEYs", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &key[j]); + key[j+8] = key[j]; + key[j+16] = key[j]; + } + fputs(buf, resp); + continue; + } + } else { + /* KEY1 = ... */ + if (strncmp(buf, "KEY1", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &key[j]); + } + fputs(buf, resp); + continue; + } + /* KEY2 = ... */ + if (strncmp(buf, "KEY2", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=8; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &key[j]); + } + fputs(buf, resp); + continue; + } + /* KEY3 = ... */ + if (strncmp(buf, "KEY3", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=16; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &key[j]); + } + fputs(buf, resp); + continue; + } + } + + /* IV = ... */ + if (strncmp(buf, "IV", 2) == 0) { + mode = NSS_DES_EDE3_CBC; + i = 2; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j<sizeof iv; i+=2,j++) { + hex_from_2char(&buf[i], &iv[j]); + } + fputs(buf, resp); + continue; + } + + /* PLAINTEXT = ... */ + if (strncmp(buf, "PLAINTEXT", 9) == 0) { + /* sanity check */ + if (crypt != ENCRYPT) { + goto loser; + } + i = 9; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &plaintext[j]); + } + plaintextlen = j; + rv = tdea_encrypt_buf(mode, key, + (mode == NSS_DES_EDE3) ? NULL : iv, + ciphertext, &ciphertextlen, sizeof ciphertext, + plaintext, plaintextlen); + if (rv != SECSuccess) { + goto loser; + } + + fputs(buf, resp); + fputs("CIPHERTEXT = ", resp); + to_hex_str(buf, ciphertext, ciphertextlen); + fputs(buf, resp); + fputc('\n', resp); + continue; + } + /* CIPHERTEXT = ... */ + if (strncmp(buf, "CIPHERTEXT", 10) == 0) { + /* sanity check */ + if (crypt != DECRYPT) { + goto loser; + } + + i = 10; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &ciphertext[j]); + } + ciphertextlen = j; + + rv = tdea_decrypt_buf(mode, key, + (mode == NSS_DES_EDE3) ? NULL : iv, + plaintext, &plaintextlen, sizeof plaintext, + ciphertext, ciphertextlen); + if (rv != SECSuccess) { + goto loser; + } + + fputs(buf, resp); + fputs("PLAINTEXT = ", resp); + to_hex_str(buf, plaintext, plaintextlen); + fputs(buf, resp); + fputc('\n', resp); + continue; + } } + +loser: + fclose(req); } -void -des_sub_tbl_kat(int mode, PRBool encrypt, unsigned int len, - unsigned char *key, unsigned char *iv, - unsigned char *inp) +/* +* Set the parity bit for the given byte +*/ +BYTE odd_parity( BYTE in) { - int i; - unsigned int olen; - unsigned char keyin[24]; - unsigned char out[8]; - char keystr[17], ivstr[17], instr[17], outstr[17]; - char *ptty = (len == 8) ? "PT" : "PLAINTEXT"; - char *ctty = (len == 8) ? "CT" : "CIPHERTEXT"; - char tchar = (len == 8) ? '\t' : '\n'; - DESContext *cx1 = NULL, *cx2 = NULL; - memset(keyin, 0, sizeof keyin); - memset(keystr, 0, sizeof keystr); - memset(ivstr, 0, sizeof ivstr); - memset(instr, 0, sizeof instr); - memset(outstr, 0, sizeof outstr); - for (i=0; i<19; i++) { - memcpy(keyin, table4_key[i], 8); - memcpy(keyin+8, table4_key[i], 8); - memcpy(keyin+16, table4_key[i], 8); - cx1 = DES_CreateContext(keyin, iv, mode, PR_TRUE); - if (!encrypt) { - cx2 = DES_CreateContext(keyin, iv, mode, PR_FALSE); - } - if (len > 8) { - printf("COUNT = %d\n", i); - to_hex_str(keystr, keyin, 8); - printf("KEY1=%s\n", keystr); - to_hex_str(keystr, keyin+8, 8); - printf("KEY2=%s\n", keystr); - to_hex_str(keystr, keyin+16, 8); - printf("KEY3=%s\n", keystr); - } else { - to_hex_str(keystr, keyin, 8); - printf("%ld\tKEY=%s\t", i, keystr); - } - if (iv) { - to_hex_str(ivstr, iv, 8); - printf("IV=%s%c", ivstr, tchar); - } - DES_Encrypt(cx1, out, &olen, 8, table4_inp[i], 8); - if (encrypt) { - to_hex_str(instr, table4_inp[i], 8); - to_hex_str(outstr, out, 8); - printf("%s=%s%c%s=%s\n\n", ptty, instr, tchar, ctty, outstr); - } else { - unsigned char inv[8]; - DES_Decrypt(cx2, inv, &olen, 8, out, 8); - to_hex_str(instr, out, 8); - to_hex_str(outstr, inv, 8); - printf("%s=%s%c%s=%s\n\n", ctty, instr, tchar, ptty, outstr); - } - DES_DestroyContext(cx1, PR_TRUE); - if (cx2) { - DES_DestroyContext(cx2, PR_TRUE); - } - } + BYTE out = in; + in ^= in >> 4; + in ^= in >> 2; + in ^= in >> 1; + return (BYTE)(out ^ !(in & 1)); } -unsigned char make_odd_parity(unsigned char b) +/* + * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j] + * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes. + */ +void +tdea_mct_next_keys(unsigned char *key, + const unsigned char *text_2, const unsigned char *text_1, + const unsigned char *text, unsigned int numKeys) { - int i; - int sum = 0; - for (i=1; i<8; i++) { - sum += (b & (1 << i)) ? 1 : 0; + int k; + + /* key1[i+1] = key1[i] xor PT/CT[j] */ + for (k=0; k<8; k++) { + key[k] ^= text[k]; + } + /* key2 */ + if (numKeys == 2 || numKeys == 3) { + /* key2 independent */ + for (k=8; k<16; k++) { + /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */ + key[k] ^= text_1[k-8]; + } + } else { + /* key2 == key 1 */ + for (k=8; k<16; k++) { + /* key2[i+1] = KEY2[i] xor PT/CT[j] */ + key[k] = key[k-8]; + } } - if (sum & 0x01) { - return (b & 0xfe); + /* key3 */ + if (numKeys == 1 || numKeys == 2) { + /* key3 == key 1 */ + for (k=16; k<24; k++) { + /* key3[i+1] = KEY3[i] xor PT/CT[j] */ + key[k] = key[k-16]; + } } else { - return (b | 0x01); + /* key3 independent */ + for (k=16; k<24; k++) { + /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */ + key[k] ^= text_2[k-16]; + } + } + /* set the parity bits */ + for (k=0; k<24; k++) { + key[k] = odd_parity(key[k]); + } +} + +/* + * Perform the Monte Carlo Test + * + * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC + * crypt = ENCRYPT || DECRYPT + * inputtext = plaintext or Cyphertext depending on the value of crypt + * inputlength is expected to be size 8 bytes + * iv = needs to be set for NSS_DES_EDE3_CBC mode + * resp = is the output response file. + */ + void +tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys, + unsigned int crypt, unsigned char* inputtext, + unsigned int inputlength, unsigned char* iv, FILE *resp) { + + int i, j; + unsigned char outputtext_1[8]; /* PT/CT[j-1] */ + unsigned char outputtext_2[8]; /* PT/CT[j-2] */ + char buf[80]; /* holds one line from the input REQUEST file. */ + unsigned int outputlen; + unsigned char outputtext[8]; + + + SECStatus rv; + + if (mode == NSS_DES_EDE3 && iv != NULL) { + printf("IV must be NULL for NSS_DES_EDE3 mode"); + goto loser; + } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) { + printf("IV must not be NULL for NSS_DES_EDE3_CBC mode"); + goto loser; + } + + /* loop 400 times */ + for (i=0; i<400; i++) { + /* if i == 0 CV[0] = IV not necessary */ + /* record the count and key values and plainText */ + sprintf(buf, "COUNT = %d\n", i); + fputs(buf, resp); + /* Output KEY1[i] */ + fputs("KEY1 = ", resp); + to_hex_str(buf, key, 8); + fputs(buf, resp); + fputc('\n', resp); + /* Output KEY2[i] */ + fputs("KEY2 = ", resp); + to_hex_str(buf, &key[8], 8); + fputs(buf, resp); + fputc('\n', resp); + /* Output KEY3[i] */ + fputs("KEY3 = ", resp); + to_hex_str(buf, &key[16], 8); + fputs(buf, resp); + fputc('\n', resp); + if (mode == NSS_DES_EDE3_CBC) { + /* Output CV[i] */ + fputs("IV = ", resp); + to_hex_str(buf, iv, 8); + fputs(buf, resp); + fputc('\n', resp); + } + if (crypt == ENCRYPT) { + /* Output PT[0] */ + fputs("PLAINTEXT = ", resp); + } else { + /* Output CT[0] */ + fputs("CIPHERTEXT = ", resp); + } + + to_hex_str(buf, inputtext, inputlength); + fputs(buf, resp); + fputc('\n', resp); + + /* loop 10,000 times */ + for (j=0; j<10000; j++) { + + outputlen = 0; + if (crypt == ENCRYPT) { + /* inputtext == ciphertext outputtext == plaintext*/ + rv = tdea_encrypt_buf(mode, key, + (mode == NSS_DES_EDE3) ? NULL : iv, + outputtext, &outputlen, 8, + inputtext, 8); + } else { + /* inputtext == plaintext outputtext == ciphertext */ + rv = tdea_decrypt_buf(mode, key, + (mode == NSS_DES_EDE3) ? NULL : iv, + outputtext, &outputlen, 8, + inputtext, 8); + } + + if (rv != SECSuccess) { + goto loser; + } + if (outputlen != inputlength) { + goto loser; + } + + if (mode == NSS_DES_EDE3_CBC) { + if (crypt == ENCRYPT) { + if (j == 0) { + /*P[j+1] = CV[0] */ + memcpy(inputtext, iv, 8); + } else { + /* p[j+1] = C[j-1] */ + memcpy(inputtext, outputtext_1, 8); + } + /* CV[j+1] = C[j] */ + memcpy(iv, outputtext, 8); + if (j != 9999) { + /* save C[j-1] */ + memcpy(outputtext_1, outputtext, 8); + } + } else { /* DECRYPT */ + /* CV[j+1] = C[j] */ + memcpy(iv, inputtext, 8); + /* C[j+1] = P[j] */ + memcpy(inputtext, outputtext, 8); + } + } else { + /* ECB mode PT/CT[j+1] = CT/PT[j] */ + memcpy(inputtext, outputtext, 8); + } + + /* Save PT/CT[j-2] and PT/CT[j-1] */ + if (j==9997) memcpy(outputtext_2, outputtext, 8); + if (j==9998) memcpy(outputtext_1, outputtext, 8); + /* done at the end of the for(j) loop */ + } + + + if (crypt == ENCRYPT) { + /* Output CT[j] */ + fputs("CIPHERTEXT = ", resp); + } else { + /* Output PT[j] */ + fputs("PLAINTEXT = ", resp); + } + to_hex_str(buf, outputtext, 8); + fputs(buf, resp); + fputc('\n', resp); + + /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2] + * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j] + */ + tdea_mct_next_keys(key, outputtext_2, + outputtext_1, outputtext, numKeys); + + if (mode == NSS_DES_EDE3_CBC) { + /* taken care of in the j=9999 iteration */ + if (crypt == ENCRYPT) { + /* P[i] = C[j-1] */ + /* CV[i] = C[j] */ + } else { + /* taken care of in the j=9999 iteration */ + /* CV[i] = C[j] */ + /* C[i] = P[j] */ + } + } else { + /* ECB PT/CT[i] = PT/CT[j] */ + memcpy(inputtext, outputtext, 8); + } + /* done at the end of the for(i) loop */ + fputc('\n', resp); } + +loser: + return; } +/* + * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes. + * by gathering the input from the request file, and then + * calling tdea_mct_test. + * + * reqfn is the pathname of the input REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ void -des_modes(int mode, PRBool encrypt, unsigned int len, - const unsigned char *key, const unsigned char *iv, - const unsigned char *inp, int keymode) +tdea_mct(int mode, char *reqfn) { int i, j; - unsigned int olen; - unsigned char keyin[24]; - unsigned char in[8]; - unsigned char cv[8]; - unsigned char cv0[8]; - unsigned char in0[8]; - unsigned char out[8]; - unsigned char cj9998[8], cj9997[8]; - char keystr[17], ivstr[17], instr[17], outstr[17]; - char *ptty = (len == 8) ? "PT" : "PLAINTEXT"; - char *ctty = (len == 8) ? "CT" : "CIPHERTEXT"; - char tchar = (len == 8) ? '\t' : '\n'; - DESContext *cx1 = NULL; - memset(keystr, 0, sizeof keystr); - memset(ivstr, 0, sizeof ivstr); - memset(instr, 0, sizeof instr); - memset(outstr, 0, sizeof outstr); - memcpy(in, inp, 8); - if (iv) memcpy(cv, iv, 8); - memcpy(keyin, key, len); - for (i=0; i<400; i++) { - if (iv) memcpy(cv0, cv, 8); - memcpy(in0, in, 8); - for (j=0; j<10000; j++) { - if (encrypt) { - cx1 = DES_CreateContext(keyin, cv, mode, PR_TRUE); - DES_Encrypt(cx1, out, &olen, 8, in, 8); - } else { - cx1 = DES_CreateContext(keyin, cv, mode, PR_FALSE); - DES_Decrypt(cx1, out, &olen, 8, in, 8); - } - if (j==9997) memcpy(cj9997, out, 8); - if (j==9998) memcpy(cj9998, out, 8); - if (iv) { - if (encrypt) { - memcpy(in, cv, 8); - memcpy(cv, out, 8); - } else { - memcpy(cv, in, 8); - memcpy(in, out, 8); - } - } else { - memcpy(in, out, 8); - } - DES_DestroyContext(cx1, PR_TRUE); - } - if (keymode > 0) { - printf("COUNT = %d\n", i); - to_hex_str(keystr, keyin, 8); - printf("KEY1=%s\n", keystr); - to_hex_str(keystr, keyin+8, 8); - printf("KEY2=%s\n", keystr); - to_hex_str(keystr, keyin+16, 8); - printf("KEY3=%s\n", keystr); - } else { - to_hex_str(keystr, keyin, 8); - printf("%ld\tKEY=%s\t", i, keystr); - } - if (iv) { - to_hex_str(ivstr, cv0, 8); - printf("CV=%s%c", ivstr, tchar); - } - to_hex_str(instr, in0, 8); - to_hex_str(outstr, out, 8); - if (encrypt) { - printf("%s=%s%c%s=%s\n\n", ptty, instr, tchar, ctty, outstr); - } else { - printf("%s=%s%c%s=%s\n\n", ctty, instr, tchar, ptty, outstr); - } - for (j=0; j<8; j++) { - keyin[j] ^= out[j]; - keyin[j] = make_odd_parity(keyin[j]); - if (keymode == 0) continue; - if (keymode > 1) { - keyin[j+8] ^= cj9998[j]; - keyin[j+8] = make_odd_parity(keyin[j+8]); - } else { - keyin[j+8] = keyin[j]; - } - if (keymode > 2) { - keyin[j+16] ^= cj9997[j]; - keyin[j+16] = make_odd_parity(keyin[j+16]); - } else { - keyin[j+16] = keyin[j]; - } - } + char buf[80]; /* holds one line from the input REQUEST file. */ + FILE *req; /* input stream from the REQUEST file */ + FILE *resp; /* output stream to the RESPONSE file */ + unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */ + unsigned char key[24]; /* TDEA 3 key bundle */ + unsigned int numKeys = 0; + unsigned char plaintext[8]; /* PT[j] */ + unsigned char ciphertext[8]; /* CT[j] */ + unsigned char iv[8]; + + /* zeroize the variables for the test with this data set */ + memset(key, 0, sizeof key); + memset(plaintext, 0, sizeof plaintext); + memset(ciphertext, 0, sizeof ciphertext); + memset(iv, 0, sizeof iv); + + req = fopen(reqfn, "r"); + resp = stdout; + while (fgets(buf, sizeof buf, req) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, resp); + continue; + } + /* [ENCRYPT] or [DECRYPT] */ + if (buf[0] == '[') { + if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { + crypt = ENCRYPT; + } else { + crypt = DECRYPT; + } + fputs(buf, resp); + continue; + } + /* NumKeys */ + if (strncmp(&buf[0], "NumKeys", 7) == 0) { + i = 7; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + numKeys = atoi(&buf[i]); + continue; + } + /* KEY1 = ... */ + if (strncmp(buf, "KEY1", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &key[j]); + } + continue; + } + /* KEY2 = ... */ + if (strncmp(buf, "KEY2", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=8; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &key[j]); + } + continue; + } + /* KEY3 = ... */ + if (strncmp(buf, "KEY3", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=16; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &key[j]); + } + continue; + } + + /* IV = ... */ + if (strncmp(buf, "IV", 2) == 0) { + i = 2; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j<sizeof iv; i+=2,j++) { + hex_from_2char(&buf[i], &iv[j]); + } + continue; + } + + /* PLAINTEXT = ... */ + if (strncmp(buf, "PLAINTEXT", 9) == 0) { + + /* sanity check */ + if (crypt != ENCRYPT) { + goto loser; + } + /* PT[0] = PT */ + i = 9; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j<sizeof plaintext; i+=2,j++) { + hex_from_2char(&buf[i], &plaintext[j]); + } + + /* do the Monte Carlo test */ + if (mode==NSS_DES_EDE3) { + tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp); + } else { + tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp); + } + continue; + } + /* CIPHERTEXT = ... */ + if (strncmp(buf, "CIPHERTEXT", 10) == 0) { + /* sanity check */ + if (crypt != DECRYPT) { + goto loser; + } + /* CT[0] = CT */ + i = 10; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &ciphertext[j]); + } + + /* do the Monte Carlo test */ + if (mode==NSS_DES_EDE3) { + tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp); + } else { + tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp); + } + continue; + } } + +loser: + fclose(req); } + SECStatus aes_encrypt_buf( int mode, @@ -1797,152 +1853,6 @@ void write_compact_string(FILE *out, unsigned char *hash, unsigned int len) fseek(out, 0, SEEK_END); } -void do_shs_type3(FILE *out, unsigned char *M, unsigned int len) -{ - int i, j, a; - unsigned char zero[30]; - unsigned char iword[4]; - unsigned int l = len; - char hashstr[41]; - SHA1Context *cx; - memset(zero, 0, sizeof zero); - for (j=0; j<100; j++) { - cx = SHA1_NewContext(); - for (i=1; i<=50000; i++) { - SHA1_Begin(cx); - SHA1_Update(cx, M, l); - a = j/4 + 3; - SHA1_Update(cx, zero, a); - iword[3] = (char)i; - iword[2] = (char)(i >> 8); - iword[1] = (char)(i >> 16); - iword[0] = (char)(i >> 24); - SHA1_Update(cx, iword, 4); - SHA1_End(cx, M, &l, 20); - } - SHA1_DestroyContext(cx, PR_TRUE); - to_hex_str_cap(hashstr, M, l); - hashstr[40] = '\0'; - fprintf(out, "%s ^", hashstr); - if (j<99) fprintf(out, "\n"); - } -} - -void -shs_test(char *reqfn) -{ - char buf[80]; - FILE *shareq, *sharesp; - char readbuf[64]; - int i, nr; - int newline, skip, r_z, r_b, r_n, r, b, z, n, reading; - unsigned char hash[20]; - char hashstr[41]; - unsigned char input[13000]; - int next_bit = 0; - int shs_type = 0; - shareq = fopen(reqfn, "r"); - sharesp = stdout; - newline = 1; - reading = skip = r_z = r_b = r_n = z = r = n = 0; - while ((nr = fread(buf, 1, sizeof buf, shareq)) > 0) { - for (i=0; i<nr; i++) { - if (newline) { - if (buf[i] == '#' || buf[i] == 'D' || buf[i] == '<') { - skip = 1; - } else if (buf[i] == 'H') { - skip = 0; - shs_type++; - fprintf(sharesp, "H>SHS Type %d Hashes<H", shs_type); - } else if (isdigit(buf[i])) { - r_z = 1; - readbuf[r++] = buf[i]; - } - newline = (buf[i] == '\n') ? 1 : 0; - } else { - if (buf[i] == '\n' && !r_n) { - skip = r_z = r_n = 0; - newline = 1; - } else if (r_z) { - if (buf[i] == ' ') { - r_z = 0; - readbuf[r] = '\0'; - z = atoi(readbuf); - r_b = 1; - r = 0; - } else if (isdigit(buf[i])) { - readbuf[r++] = buf[i]; - } - } else if (r_b) { - if (buf[i] == ' ') { - r_b = 0; - readbuf[r] = '\0'; - b = atoi(readbuf); - r_n = 1; - r = 0; - } else if (isdigit(buf[i])) { - readbuf[r++] = buf[i]; - } - } else if (r_n) { - if (buf[i] == ' ') { - readbuf[r++] = '\0'; - n = atoi(readbuf); - if (b == 0) { - next_bit += n; - b = 1; - } else { - int next_byte = next_bit / 8; - int shift = next_bit % 8; - unsigned char m = 0xff; - if (n < 8 - shift) { - m <<= (8 - n); - m >>= shift; - input[next_byte] |= m; - next_bit += n; - } else { - m >>= shift; - input[next_byte++] |= m; - next_bit += 8 - shift; - n -= (8 - shift); - while (n > 8) { - m = 0xff; - input[next_byte++] |= m; - next_bit += 8; - n -= 8; - } - if (n > 0) { - m = 0xff << (8 - n); - input[next_byte] |= m; - next_bit += n; - } - } - b = 0; - } - r = 0; - } else if (buf[i] == '^') { - r_n = 0; - if (shs_type < 3) { - SHA1_HashBuf(hash, input, next_bit/8); - to_hex_str_cap(hashstr, hash, sizeof hash); - hashstr[40] = '\0'; - fprintf(sharesp, "%s ^", hashstr); - memset(input, 0, sizeof input); - next_bit = 0; - } else { - do_shs_type3(sharesp, input, next_bit/8); - } - } else if (isdigit(buf[i])) { - readbuf[r++] = buf[i]; - } - } - } - if (skip || newline) { - fprintf(sharesp, "%c", buf[i]); - } - } - } -} - int get_next_line(FILE *req, char *key, char *val, FILE *rsp) { int ignore = 0; @@ -1972,644 +1882,2615 @@ int get_next_line(FILE *req, char *key, char *val, FILE *rsp) return (c == EOF) ? -1 : ignore; } +#ifdef NSS_ENABLE_ECC +typedef struct curveNameTagPairStr { + char *curveName; + SECOidTag curveOidTag; +} CurveNameTagPair; + +#define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1 +/* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */ + +static CurveNameTagPair nameTagPair[] = +{ + { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, + { "nistk163", SEC_OID_SECG_EC_SECT163K1}, + { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, + { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, + { "nistb163", SEC_OID_SECG_EC_SECT163R2}, + { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, + { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, + { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, + { "nistk233", SEC_OID_SECG_EC_SECT233K1}, + { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, + { "nistb233", SEC_OID_SECG_EC_SECT233R1}, + { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, + { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, + { "nistk283", SEC_OID_SECG_EC_SECT283K1}, + { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, + { "nistb283", SEC_OID_SECG_EC_SECT283R1}, + { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, + { "nistk409", SEC_OID_SECG_EC_SECT409K1}, + { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, + { "nistb409", SEC_OID_SECG_EC_SECT409R1}, + { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, + { "nistk571", SEC_OID_SECG_EC_SECT571K1}, + { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, + { "nistb571", SEC_OID_SECG_EC_SECT571R1}, + { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, + { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, + { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, + { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, + { "secp192r1", SEC_OID_SECG_EC_SECP192R1}, + { "nistp192", SEC_OID_SECG_EC_SECP192R1}, + { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, + { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, + { "nistp224", SEC_OID_SECG_EC_SECP224R1}, + { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, + { "secp256r1", SEC_OID_SECG_EC_SECP256R1}, + { "nistp256", SEC_OID_SECG_EC_SECP256R1}, + { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, + { "nistp384", SEC_OID_SECG_EC_SECP384R1}, + { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, + { "nistp521", SEC_OID_SECG_EC_SECP521R1}, + + { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, + { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, + { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, + { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, + { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, + { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, + + { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, + { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, + { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, + { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, + { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, + { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, + { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, + { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, + { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, + { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, + { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, + { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, + { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, + { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, + { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, + { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, + { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, + { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, + { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, + { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, + + { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, + { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, + { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, + { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, + + { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, + { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, + { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, + { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, +}; + +static SECKEYECParams * +getECParams(const char *curve) +{ + SECKEYECParams *ecparams; + SECOidData *oidData = NULL; + SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ + int i, numCurves; + + if (curve != NULL) { + numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); + for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); + i++) { + if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) + curveOidTag = nameTagPair[i].curveOidTag; + } + } + + /* Return NULL if curve name is not recognized */ + if ((curveOidTag == SEC_OID_UNKNOWN) || + (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { + fprintf(stderr, "Unrecognized elliptic curve %s\n", curve); + return NULL; + } + + ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); + + /* + * ecparams->data needs to contain the ASN encoding of an object ID (OID) + * representing the named curve. The actual OID is in + * oidData->oid.data so we simply prepend 0x06 and OID length + */ + ecparams->data[0] = SEC_ASN1_OBJECT_ID; + ecparams->data[1] = oidData->oid.len; + memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); + + return ecparams; +} + +/* + * Perform the ECDSA Key Pair Generation Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ void -dss_test(char *reqdir, char *rspdir) +ecdsa_keypair_test(char *reqfn) { - char filename[128]; - char key[24], val[1024]; - FILE *req, *rsp; - unsigned int mod; - SECItem digest = { 0 }, sig = { 0 }; - DSAPublicKey pubkey = { 0 }; - DSAPrivateKey privkey = { 0 }; - PQGParams params; - PQGVerify verify; - unsigned int i; - int j, rv; - goto do_pqggen; -#if 0 - /* primality test */ -do_prime: - sprintf(filename, "%s/prime.req", reqdir); - req = fopen(filename, "r"); - sprintf(filename, "%s/prime.rsp", rspdir); - rsp = fopen(filename, "w"); - while ((rv = get_next_line(req, key, val, rsp)) >= 0) { - if (rv == 0) { - if (strcmp(key, "mod") == 0) { - mod = atoi(val); - fprintf(rsp, "[mod=%d]\n", mod); - } else if (strcmp(key, "Prime") == 0) { - unsigned char octets[128]; - mp_int mp; - fprintf(rsp, "Prime= %s\n", val); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, octets + i); + char buf[256]; /* holds one line from the input REQUEST file + * or to the output RESPONSE file. + * needs to be large enough to hold the longest + * line "Qx = <144 hex digits>\n". + */ + FILE *ecdsareq; /* input stream from the REQUEST file */ + FILE *ecdsaresp; /* output stream to the RESPONSE file */ + char curve[16]; /* "nistxddd" */ + ECParams *ecparams; + int N; + int i; + unsigned int len; + + ecdsareq = fopen(reqfn, "r"); + ecdsaresp = stdout; + strcpy(curve, "nist"); + while (fgets(buf, sizeof buf, ecdsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, ecdsaresp); + continue; + } + /* [X-ddd] */ + if (buf[0] == '[') { + const char *src; + char *dst; + SECKEYECParams *encodedparams; + + src = &buf[1]; + dst = &curve[4]; + *dst++ = tolower(*src); + src += 2; /* skip the hyphen */ + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst = '\0'; + encodedparams = getECParams(curve); + if (encodedparams == NULL) { + goto loser; + } + if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { + goto loser; + } + SECITEM_FreeItem(encodedparams, PR_TRUE); + fputs(buf, ecdsaresp); + continue; + } + /* N = x */ + if (buf[0] == 'N') { + if (sscanf(buf, "N = %d", &N) != 1) { + goto loser; + } + for (i = 0; i < N; i++) { + ECPrivateKey *ecpriv; + + if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) { + goto loser; } - mp_init(&mp); - mp_read_unsigned_octets(&mp, octets, i); - if (mpp_pprime(&mp, 50) == MP_YES) { - fprintf(rsp, "result= P\n"); - } else { - fprintf(rsp, "result= F\n"); + fputs("d = ", ecdsaresp); + to_hex_str(buf, ecpriv->privateValue.data, + ecpriv->privateValue.len); + fputs(buf, ecdsaresp); + fputc('\n', ecdsaresp); + if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) + != SECSuccess) { + goto loser; + } + len = ecpriv->publicValue.len; + if (len%2 == 0) { + goto loser; } + len = (len-1)/2; + if (ecpriv->publicValue.data[0] + != EC_POINT_FORM_UNCOMPRESSED) { + goto loser; + } + fputs("Qx = ", ecdsaresp); + to_hex_str(buf, &ecpriv->publicValue.data[1], len); + fputs(buf, ecdsaresp); + fputc('\n', ecdsaresp); + fputs("Qy = ", ecdsaresp); + to_hex_str(buf, &ecpriv->publicValue.data[1+len], len); + fputs(buf, ecdsaresp); + fputc('\n', ecdsaresp); + fputc('\n', ecdsaresp); + PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); } + PORT_FreeArena(ecparams->arena, PR_FALSE); + continue; } } - fclose(req); - fclose(rsp); -#endif -do_pqggen: - /* PQG Gen */ - sprintf(filename, "%s/pqg.req", reqdir); - req = fopen(filename, "r"); - sprintf(filename, "%s/pqg.rsp", rspdir); - rsp = fopen(filename, "w"); - while ((rv = get_next_line(req, key, val, rsp)) >= 0) { - if (rv == 0) { - if (strcmp(key, "mod") == 0) { - mod = atoi(val); - fprintf(rsp, "[mod=%d]\n", mod); - } else if (strcmp(key, "N") == 0) { - char str[264]; - unsigned int jj; - int N = atoi(val); - for (i=0; i<N; i++) { - PQGParams *pqg; - PQGVerify *vfy; - PQG_ParamGenSeedLen(PQG_PBITS_TO_INDEX(mod), 20, &pqg, &vfy); -#if 0 - if (!(vfy->seed.data[0] & 0x80)) { - to_hex_str(str, vfy->seed.data, vfy->seed.len); - fprintf(stderr, "rejected %s\n", str); - --i; - continue; - } -#endif - to_hex_str(str, pqg->prime.data, pqg->prime.len); - fprintf(rsp, "P= %s\n", str); - to_hex_str(str, pqg->subPrime.data, pqg->subPrime.len); - fprintf(rsp, "Q= %s\n", str); - to_hex_str(str, pqg->base.data, pqg->base.len); - fprintf(rsp, "G= %s\n", str); - to_hex_str(str, vfy->seed.data, vfy->seed.len); - fprintf(rsp, "Seed= %s\n", str); - to_hex_str(str, vfy->h.data, vfy->h.len); - fprintf(rsp, "H= "); - for (jj=vfy->h.len; jj<pqg->prime.len; jj++) { - fprintf(rsp, "00"); - } - fprintf(rsp, "%s\n", str); - fprintf(rsp, "c= %d\n", vfy->counter); - } +loser: + fclose(ecdsareq); +} + +/* + * Perform the ECDSA Public Key Validation Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +ecdsa_pkv_test(char *reqfn) +{ + char buf[256]; /* holds one line from the input REQUEST file. + * needs to be large enough to hold the longest + * line "Qx = <144 hex digits>\n". + */ + FILE *ecdsareq; /* input stream from the REQUEST file */ + FILE *ecdsaresp; /* output stream to the RESPONSE file */ + char curve[16]; /* "nistxddd" */ + ECParams *ecparams = NULL; + SECItem pubkey; + unsigned int i; + unsigned int len; + PRBool keyvalid = PR_TRUE; + + ecdsareq = fopen(reqfn, "r"); + ecdsaresp = stdout; + strcpy(curve, "nist"); + pubkey.data = NULL; + while (fgets(buf, sizeof buf, ecdsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, ecdsaresp); + continue; + } + /* [X-ddd] */ + if (buf[0] == '[') { + const char *src; + char *dst; + SECKEYECParams *encodedparams; + + src = &buf[1]; + dst = &curve[4]; + *dst++ = tolower(*src); + src += 2; /* skip the hyphen */ + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst = '\0'; + if (ecparams != NULL) { + PORT_FreeArena(ecparams->arena, PR_FALSE); + ecparams = NULL; + } + encodedparams = getECParams(curve); + if (encodedparams == NULL) { + goto loser; + } + if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { + goto loser; + } + SECITEM_FreeItem(encodedparams, PR_TRUE); + len = (ecparams->fieldID.size + 7) >> 3; + if (pubkey.data != NULL) { + PORT_Free(pubkey.data); + pubkey.data = NULL; + } + SECITEM_AllocItem(NULL, &pubkey, 2*len+1); + if (pubkey.data == NULL) { + goto loser; + } + pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED; + fputs(buf, ecdsaresp); + continue; + } + /* Qx = ... */ + if (strncmp(buf, "Qx", 2) == 0) { + fputs(buf, ecdsaresp); + i = 2; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]); + continue; + } + /* Qy = ... */ + if (strncmp(buf, "Qy", 2) == 0) { + fputs(buf, ecdsaresp); + if (!keyvalid) { + fputs("Result = F\n", ecdsaresp); + continue; + } + i = 2; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + keyvalid = from_hex_str(&pubkey.data[1+len], len, &buf[i]); + if (!keyvalid) { + fputs("Result = F\n", ecdsaresp); + continue; } + if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) { + fputs("Result = P\n", ecdsaresp); + } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) { + fputs("Result = F\n", ecdsaresp); + } else { + goto loser; + } + continue; } } - fclose(req); - fclose(rsp); - return; -do_pqgver: - /* PQG Verification */ - sprintf(filename, "%s/verpqg.req", reqdir); - req = fopen(filename, "r"); - sprintf(filename, "%s/verpqg.rsp", rspdir); - rsp = fopen(filename, "w"); - memset(¶ms, 0, sizeof(params)); - memset(&verify, 0, sizeof(verify)); - while ((rv = get_next_line(req, key, val, rsp)) >= 0) { - if (rv == 0) { - if (strcmp(key, "mod") == 0) { - mod = atoi(val); - fprintf(rsp, "[mod=%d]\n", mod); - } else if (strcmp(key, "P") == 0) { - if (params.prime.data) { - SECITEM_ZfreeItem(¶ms.prime, PR_FALSE); - } - SECITEM_AllocItem(NULL, ¶ms.prime, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, params.prime.data + i); - } - fprintf(rsp, "P= %s\n", val); - } else if (strcmp(key, "Q") == 0) { - if (params.subPrime.data) { - SECITEM_ZfreeItem(¶ms.subPrime, PR_FALSE); - } - SECITEM_AllocItem(NULL, ¶ms.subPrime,strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, params.subPrime.data + i); - } - fprintf(rsp, "Q= %s\n", val); - } else if (strcmp(key, "G") == 0) { - if (params.base.data) { - SECITEM_ZfreeItem(¶ms.base, PR_FALSE); - } - SECITEM_AllocItem(NULL, ¶ms.base, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, params.base.data + i); - } - fprintf(rsp, "G= %s\n", val); - } else if (strcmp(key, "Seed") == 0) { - if (verify.seed.data) { - SECITEM_ZfreeItem(&verify.seed, PR_FALSE); - } - SECITEM_AllocItem(NULL, &verify.seed, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, verify.seed.data + i); - } - fprintf(rsp, "Seed= %s\n", val); - } else if (strcmp(key, "H") == 0) { - if (verify.h.data) { - SECITEM_ZfreeItem(&verify.h, PR_FALSE); - } - SECITEM_AllocItem(NULL, &verify.h, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, verify.h.data + i); - } - fprintf(rsp, "H= %s\n", val); - } else if (strcmp(key, "c") == 0) { - SECStatus pqgrv, result; - verify.counter = atoi(val); - fprintf(rsp, "c= %d\n", verify.counter); - pqgrv = PQG_VerifyParams(¶ms, &verify, &result); - if (result == SECSuccess) { - fprintf(rsp, "result= P\n"); +loser: + if (ecparams != NULL) { + PORT_FreeArena(ecparams->arena, PR_FALSE); + } + if (pubkey.data != NULL) { + PORT_Free(pubkey.data); + } + fclose(ecdsareq); +} + +/* + * Perform the ECDSA Signature Generation Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +ecdsa_siggen_test(char *reqfn) +{ + char buf[1024]; /* holds one line from the input REQUEST file + * or to the output RESPONSE file. + * needs to be large enough to hold the longest + * line "Msg = <256 hex digits>\n". + */ + FILE *ecdsareq; /* input stream from the REQUEST file */ + FILE *ecdsaresp; /* output stream to the RESPONSE file */ + char curve[16]; /* "nistxddd" */ + ECParams *ecparams = NULL; + int i, j; + unsigned int len; + unsigned char msg[512]; /* message to be signed (<= 128 bytes) */ + unsigned int msglen; + unsigned char sha1[20]; /* SHA-1 hash (160 bits) */ + unsigned char sig[2*MAX_ECKEY_LEN]; + SECItem signature, digest; + + ecdsareq = fopen(reqfn, "r"); + ecdsaresp = stdout; + strcpy(curve, "nist"); + while (fgets(buf, sizeof buf, ecdsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, ecdsaresp); + continue; + } + /* [X-ddd] */ + if (buf[0] == '[') { + const char *src; + char *dst; + SECKEYECParams *encodedparams; + + src = &buf[1]; + dst = &curve[4]; + *dst++ = tolower(*src); + src += 2; /* skip the hyphen */ + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst = '\0'; + if (ecparams != NULL) { + PORT_FreeArena(ecparams->arena, PR_FALSE); + ecparams = NULL; + } + encodedparams = getECParams(curve); + if (encodedparams == NULL) { + goto loser; + } + if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { + goto loser; + } + SECITEM_FreeItem(encodedparams, PR_TRUE); + fputs(buf, ecdsaresp); + continue; + } + /* Msg = ... */ + if (strncmp(buf, "Msg", 3) == 0) { + ECPrivateKey *ecpriv; + + i = 3; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &msg[j]); + } + msglen = j; + if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) { + goto loser; + } + fputs(buf, ecdsaresp); + + if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) { + goto loser; + } + if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) + != SECSuccess) { + goto loser; + } + len = ecpriv->publicValue.len; + if (len%2 == 0) { + goto loser; + } + len = (len-1)/2; + if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) { + goto loser; + } + fputs("Qx = ", ecdsaresp); + to_hex_str(buf, &ecpriv->publicValue.data[1], len); + fputs(buf, ecdsaresp); + fputc('\n', ecdsaresp); + fputs("Qy = ", ecdsaresp); + to_hex_str(buf, &ecpriv->publicValue.data[1+len], len); + fputs(buf, ecdsaresp); + fputc('\n', ecdsaresp); + + digest.type = siBuffer; + digest.data = sha1; + digest.len = sizeof sha1; + signature.type = siBuffer; + signature.data = sig; + signature.len = sizeof sig; + if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) { + goto loser; + } + len = signature.len; + if (len%2 != 0) { + goto loser; + } + len = len/2; + fputs("R = ", ecdsaresp); + to_hex_str(buf, &signature.data[0], len); + fputs(buf, ecdsaresp); + fputc('\n', ecdsaresp); + fputs("S = ", ecdsaresp); + to_hex_str(buf, &signature.data[len], len); + fputs(buf, ecdsaresp); + fputc('\n', ecdsaresp); + + PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); + continue; + } + } +loser: + if (ecparams != NULL) { + PORT_FreeArena(ecparams->arena, PR_FALSE); + } + fclose(ecdsareq); +} + +/* + * Perform the ECDSA Signature Verification Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +ecdsa_sigver_test(char *reqfn) +{ + char buf[1024]; /* holds one line from the input REQUEST file. + * needs to be large enough to hold the longest + * line "Msg = <256 hex digits>\n". + */ + FILE *ecdsareq; /* input stream from the REQUEST file */ + FILE *ecdsaresp; /* output stream to the RESPONSE file */ + char curve[16]; /* "nistxddd" */ + ECPublicKey ecpub; + unsigned int i, j; + unsigned int flen; /* length in bytes of the field size */ + unsigned int olen; /* length in bytes of the base point order */ + unsigned char msg[512]; /* message that was signed (<= 128 bytes) */ + unsigned int msglen; + unsigned char sha1[20]; /* SHA-1 hash (160 bits) */ + unsigned char sig[2*MAX_ECKEY_LEN]; + SECItem signature, digest; + PRBool keyvalid = PR_TRUE; + PRBool sigvalid = PR_TRUE; + + ecdsareq = fopen(reqfn, "r"); + ecdsaresp = stdout; + ecpub.ecParams.arena = NULL; + strcpy(curve, "nist"); + while (fgets(buf, sizeof buf, ecdsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, ecdsaresp); + continue; + } + /* [X-ddd] */ + if (buf[0] == '[') { + const char *src; + char *dst; + SECKEYECParams *encodedparams; + ECParams *ecparams; + + src = &buf[1]; + dst = &curve[4]; + *dst++ = tolower(*src); + src += 2; /* skip the hyphen */ + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst = '\0'; + encodedparams = getECParams(curve); + if (encodedparams == NULL) { + goto loser; + } + if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { + goto loser; + } + SECITEM_FreeItem(encodedparams, PR_TRUE); + if (ecpub.ecParams.arena != NULL) { + PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE); + } + ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (ecpub.ecParams.arena == NULL) { + goto loser; + } + if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams) + != SECSuccess) { + goto loser; + } + PORT_FreeArena(ecparams->arena, PR_FALSE); + flen = (ecpub.ecParams.fieldID.size + 7) >> 3; + olen = ecpub.ecParams.order.len; + if (2*olen > sizeof sig) { + goto loser; + } + ecpub.publicValue.type = siBuffer; + ecpub.publicValue.data = NULL; + ecpub.publicValue.len = 0; + SECITEM_AllocItem(ecpub.ecParams.arena, + &ecpub.publicValue, 2*flen+1); + if (ecpub.publicValue.data == NULL) { + goto loser; + } + ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED; + fputs(buf, ecdsaresp); + continue; + } + /* Msg = ... */ + if (strncmp(buf, "Msg", 3) == 0) { + i = 3; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &msg[j]); + } + msglen = j; + if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) { + goto loser; + } + fputs(buf, ecdsaresp); + + digest.type = siBuffer; + digest.data = sha1; + digest.len = sizeof sha1; + + continue; + } + /* Qx = ... */ + if (strncmp(buf, "Qx", 2) == 0) { + fputs(buf, ecdsaresp); + i = 2; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen, + &buf[i]); + continue; + } + /* Qy = ... */ + if (strncmp(buf, "Qy", 2) == 0) { + fputs(buf, ecdsaresp); + if (!keyvalid) { + continue; + } + i = 2; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + keyvalid = from_hex_str(&ecpub.publicValue.data[1+flen], flen, + &buf[i]); + if (!keyvalid) { + continue; + } + if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue) + != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_BAD_KEY) { + keyvalid = PR_FALSE; } else { - fprintf(rsp, "result= F\n"); + goto loser; } } + continue; } - } - fclose(req); - fclose(rsp); - return; -do_keygen: - /* Key Gen */ - sprintf(filename, "%s/xy.req", reqdir); - req = fopen(filename, "r"); - sprintf(filename, "%s/xy.rsp", rspdir); - rsp = fopen(filename, "w"); - while ((rv = get_next_line(req, key, val, rsp)) >= 0); - for (j=0; j<=8; j++) { - char str[264]; - PQGParams *pqg; - PQGVerify *vfy; - fprintf(rsp, "[mod=%d]\n", 512 + j*64); - PQG_ParamGen(j, &pqg, &vfy); - to_hex_str(str, pqg->prime.data, pqg->prime.len); - fprintf(rsp, "P= %s\n", str); - to_hex_str(str, pqg->subPrime.data, pqg->subPrime.len); - fprintf(rsp, "Q= %s\n", str); - to_hex_str(str, pqg->base.data, pqg->base.len); - fprintf(rsp, "G= %s\n", str); - for (i=0; i<10; i++) { - DSAPrivateKey *dsakey; - DSA_NewKey(pqg, &dsakey); - to_hex_str(str, dsakey->privateValue.data,dsakey->privateValue.len); - fprintf(rsp, "X= %s\n", str); - to_hex_str(str, dsakey->publicValue.data, dsakey->publicValue.len); - fprintf(rsp, "Y= %s\n", str); - PORT_FreeArena(dsakey->params.arena, PR_TRUE); - dsakey = NULL; + /* R = ... */ + if (buf[0] == 'R') { + fputs(buf, ecdsaresp); + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + sigvalid = from_hex_str(sig, olen, &buf[i]); + continue; + } + /* S = ... */ + if (buf[0] == 'S') { + fputs(buf, ecdsaresp); + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + if (sigvalid) { + sigvalid = from_hex_str(&sig[olen], olen, &buf[i]); + } + signature.type = siBuffer; + signature.data = sig; + signature.len = 2*olen; + + if (!keyvalid || !sigvalid) { + fputs("Result = F\n", ecdsaresp); + } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest) + == SECSuccess) { + fputs("Result = P\n", ecdsaresp); + } else { + fputs("Result = F\n", ecdsaresp); + } + continue; } } - fclose(req); - fclose(rsp); - return; -do_siggen: - /* Signature Gen */ - sprintf(filename, "%s/gensig.req", reqdir); - req = fopen(filename, "r"); - sprintf(filename, "%s/gensig.rsp", rspdir); - rsp = fopen(filename, "w"); - while ((rv = get_next_line(req, key, val, rsp)) >= 0) { - if (rv == 0) { - if (strcmp(key, "mod") == 0) { - mod = atoi(val); - fprintf(rsp, "[mod=%d]\n", mod); - } else if (strcmp(key, "P") == 0) { - if (privkey.params.prime.data) { - SECITEM_ZfreeItem(&privkey.params.prime, PR_FALSE); - } - SECITEM_AllocItem(NULL, &privkey.params.prime, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, privkey.params.prime.data + i); - } - fprintf(rsp, "P= %s\n", val); - } else if (strcmp(key, "Q") == 0) { - if (privkey.params.subPrime.data) { - SECITEM_ZfreeItem(&privkey.params.subPrime, PR_FALSE); - } - SECITEM_AllocItem(NULL, &privkey.params.subPrime,strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, privkey.params.subPrime.data + i); - } - fprintf(rsp, "Q= %s\n", val); - } else if (strcmp(key, "G") == 0) { - if (privkey.params.base.data) { - SECITEM_ZfreeItem(&privkey.params.base, PR_FALSE); - } - SECITEM_AllocItem(NULL, &privkey.params.base, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, privkey.params.base.data + i); - } - fprintf(rsp, "G= %s\n", val); - } else if (strcmp(key, "X") == 0) { - if (privkey.privateValue.data) { - SECITEM_ZfreeItem(&privkey.privateValue, PR_FALSE); - } - SECITEM_AllocItem(NULL, &privkey.privateValue, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, privkey.privateValue.data + i); - } - fprintf(rsp, "X= %s\n", val); - } else if (strcmp(key, "Msg") == 0) { - char msg[512]; - char str[81]; - if (digest.data) { - SECITEM_ZfreeItem(&digest, PR_FALSE); - } - SECITEM_AllocItem(NULL, &digest, 20); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, msg + i); - } - msg[i] = '\0'; - /*SHA1_Hash(digest.data, msg);*/ - SHA1_HashBuf(digest.data, msg, i); - fprintf(rsp, "Msg= %s\n", val); - if (sig.data) { - SECITEM_ZfreeItem(&sig, PR_FALSE); +loser: + if (ecpub.ecParams.arena != NULL) { + PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE); + } + fclose(ecdsareq); +} +#endif /* NSS_ENABLE_ECC */ + +/* + * Perform the RNG Variable Seed Test (VST) for the RNG algorithm + * "DSA - Generation of X", used both as specified and as a generic + * purpose RNG. The presence of "Q = ..." in the REQUEST file + * indicates we are using the algorithm as specified. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +rng_vst(char *reqfn) +{ + char buf[256]; /* holds one line from the input REQUEST file. + * needs to be large enough to hold the longest + * line "XSeed = <128 hex digits>\n". + */ + FILE *rngreq; /* input stream from the REQUEST file */ + FILE *rngresp; /* output stream to the RESPONSE file */ + unsigned int i, j; + unsigned char Q[DSA_SUBPRIME_LEN]; + PRBool hasQ = PR_FALSE; + unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */ + unsigned char XKey[512/8]; + unsigned char XSeed[512/8]; + unsigned char GENX[2*SHA1_LENGTH]; + unsigned char DSAX[DSA_SUBPRIME_LEN]; + SECStatus rv; + + rngreq = fopen(reqfn, "r"); + rngresp = stdout; + while (fgets(buf, sizeof buf, rngreq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, rngresp); + continue; + } + /* [Xchange - SHA1] */ + if (buf[0] == '[') { + fputs(buf, rngresp); + continue; + } + /* Q = ... */ + if (buf[0] == 'Q') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j<sizeof Q; i+=2,j++) { + hex_from_2char(&buf[i], &Q[j]); + } + fputs(buf, rngresp); + hasQ = PR_TRUE; + continue; + } + /* "COUNT = x" begins a new data set */ + if (strncmp(buf, "COUNT", 5) == 0) { + /* zeroize the variables for the test with this data set */ + b = 0; + memset(XKey, 0, sizeof XKey); + memset(XSeed, 0, sizeof XSeed); + fputs(buf, rngresp); + continue; + } + /* b = ... */ + if (buf[0] == 'b') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + b = atoi(&buf[i]); + if (b < 160 || b > 512 || b%8 != 0) { + goto loser; + } + fputs(buf, rngresp); + continue; + } + /* XKey = ... */ + if (strncmp(buf, "XKey", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j<b/8; i+=2,j++) { + hex_from_2char(&buf[i], &XKey[j]); + } + fputs(buf, rngresp); + continue; + } + /* XSeed = ... */ + if (strncmp(buf, "XSeed", 5) == 0) { + i = 5; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j<b/8; i+=2,j++) { + hex_from_2char(&buf[i], &XSeed[j]); + } + fputs(buf, rngresp); + + rv = FIPS186Change_GenerateX(XKey, XSeed, GENX); + if (rv != SECSuccess) { + goto loser; + } + fputs("X = ", rngresp); + if (hasQ) { + rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX); + if (rv != SECSuccess) { + goto loser; } - SECITEM_AllocItem(NULL, &sig, 40); - rv = DSA_SignDigest(&privkey, &sig, &digest); - to_hex_str(str, sig.data, sig.len); - fprintf(rsp, "Sig= %s\n", str); + to_hex_str(buf, DSAX, sizeof DSAX); + } else { + to_hex_str(buf, GENX, sizeof GENX); } + fputs(buf, rngresp); + fputc('\n', rngresp); + continue; } } - fclose(req); - fclose(rsp); -do_sigver: - /* Signature Verification */ - sprintf(filename, "%s/versig.req", reqdir); - req = fopen(filename, "r"); - sprintf(filename, "%s/versig.rsp", rspdir); - rsp = fopen(filename, "w"); - while ((rv = get_next_line(req, key, val, rsp)) >= 0) { - if (rv == 0) { - if (strcmp(key, "mod") == 0) { - mod = atoi(val); - fprintf(rsp, "[mod=%d]\n", mod); - } else if (strcmp(key, "P") == 0) { - if (pubkey.params.prime.data) { - SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE); - } - SECITEM_AllocItem(NULL, &pubkey.params.prime, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, pubkey.params.prime.data + i); - } - fprintf(rsp, "P= %s\n", val); - } else if (strcmp(key, "Q") == 0) { - if (pubkey.params.subPrime.data) { - SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE); - } - SECITEM_AllocItem(NULL, &pubkey.params.subPrime, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, pubkey.params.subPrime.data + i); - } - fprintf(rsp, "Q= %s\n", val); - } else if (strcmp(key, "G") == 0) { - if (pubkey.params.base.data) { - SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE); - } - SECITEM_AllocItem(NULL, &pubkey.params.base, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, pubkey.params.base.data + i); - } - fprintf(rsp, "G= %s\n", val); - } else if (strcmp(key, "Y") == 0) { - if (pubkey.publicValue.data) { - SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE); - } - SECITEM_AllocItem(NULL, &pubkey.publicValue, strlen(val)/2); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, pubkey.publicValue.data + i); - } - fprintf(rsp, "Y= %s\n", val); - } else if (strcmp(key, "Msg") == 0) { - char msg[512]; - if (digest.data) { - SECITEM_ZfreeItem(&digest, PR_FALSE); - } - SECITEM_AllocItem(NULL, &digest, 20); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, msg + i); - } - msg[i] = '\0'; - SHA1_HashBuf(digest.data, msg, i); - /*SHA1_Hash(digest.data, msg);*/ - fprintf(rsp, "Msg= %s\n", val); - } else if (strcmp(key, "Sig") == 0) { - SECStatus rv; - if (sig.data) { - SECITEM_ZfreeItem(&sig, PR_FALSE); - } - SECITEM_AllocItem(NULL, &sig, 40); - for (i=0; i<strlen(val) / 2; i++) { - hex_from_2char(val + 2*i, sig.data + i); +loser: + fclose(rngreq); +} + +/* + * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm + * "DSA - Generation of X", used both as specified and as a generic + * purpose RNG. The presence of "Q = ..." in the REQUEST file + * indicates we are using the algorithm as specified. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +rng_mct(char *reqfn) +{ + char buf[256]; /* holds one line from the input REQUEST file. + * needs to be large enough to hold the longest + * line "XSeed = <128 hex digits>\n". + */ + FILE *rngreq; /* input stream from the REQUEST file */ + FILE *rngresp; /* output stream to the RESPONSE file */ + unsigned int i, j; + unsigned char Q[DSA_SUBPRIME_LEN]; + PRBool hasQ = PR_FALSE; + unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */ + unsigned char XKey[512/8]; + unsigned char XSeed[512/8]; + unsigned char GENX[2*SHA1_LENGTH]; + unsigned char DSAX[DSA_SUBPRIME_LEN]; + SECStatus rv; + + rngreq = fopen(reqfn, "r"); + rngresp = stdout; + while (fgets(buf, sizeof buf, rngreq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, rngresp); + continue; + } + /* [Xchange - SHA1] */ + if (buf[0] == '[') { + fputs(buf, rngresp); + continue; + } + /* Q = ... */ + if (buf[0] == 'Q') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j<sizeof Q; i+=2,j++) { + hex_from_2char(&buf[i], &Q[j]); + } + fputs(buf, rngresp); + hasQ = PR_TRUE; + continue; + } + /* "COUNT = x" begins a new data set */ + if (strncmp(buf, "COUNT", 5) == 0) { + /* zeroize the variables for the test with this data set */ + b = 0; + memset(XKey, 0, sizeof XKey); + memset(XSeed, 0, sizeof XSeed); + fputs(buf, rngresp); + continue; + } + /* b = ... */ + if (buf[0] == 'b') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + b = atoi(&buf[i]); + if (b < 160 || b > 512 || b%8 != 0) { + goto loser; + } + fputs(buf, rngresp); + continue; + } + /* XKey = ... */ + if (strncmp(buf, "XKey", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j<b/8; i+=2,j++) { + hex_from_2char(&buf[i], &XKey[j]); + } + fputs(buf, rngresp); + continue; + } + /* XSeed = ... */ + if (strncmp(buf, "XSeed", 5) == 0) { + unsigned int k; + i = 5; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j<b/8; i+=2,j++) { + hex_from_2char(&buf[i], &XSeed[j]); + } + fputs(buf, rngresp); + + for (k = 0; k < 10000; k++) { + rv = FIPS186Change_GenerateX(XKey, XSeed, GENX); + if (rv != SECSuccess) { + goto loser; } - rv = DSA_VerifyDigest(&pubkey, &sig, &digest); - fprintf(rsp, "Sig= %s\n", val); - if (rv == SECSuccess) { - fprintf(rsp, "result= P\n"); - } else { - fprintf(rsp, "result= F\n"); + } + fputs("X = ", rngresp); + if (hasQ) { + rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX); + if (rv != SECSuccess) { + goto loser; } + to_hex_str(buf, DSAX, sizeof DSAX); + } else { + to_hex_str(buf, GENX, sizeof GENX); } + fputs(buf, rngresp); + fputc('\n', rngresp); + continue; } } +loser: + fclose(rngreq); +} + +/* + * Calculate the SHA Message Digest + * + * MD = Message digest + * MDLen = length of Message Digest and SHA_Type + * msg = message to digest + * msgLen = length of message to digest + */ +SECStatus sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen) +{ + SECStatus sha_status = SECFailure; + + if (MDLen == SHA1_LENGTH) { + sha_status = SHA1_HashBuf(MD, msg, msgLen); + } else if (MDLen == SHA256_LENGTH) { + sha_status = SHA256_HashBuf(MD, msg, msgLen); + } else if (MDLen == SHA384_LENGTH) { + sha_status = SHA384_HashBuf(MD, msg, msgLen); + } else if (MDLen == SHA512_LENGTH) { + sha_status = SHA512_HashBuf(MD, msg, msgLen); + } + + return sha_status; +} + +/* + * Perform the SHA Monte Carlo Test + * + * MDLen = length of Message Digest and SHA_Type + * seed = input seed value + * resp = is the output response file. + */ +SECStatus sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp) +{ + int i, j; + unsigned int msgLen = MDLen*3; + unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */ + unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */ + unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */ + unsigned char MD_i[HASH_LENGTH_MAX]; /* MD[i] */ + unsigned char msg[HASH_LENGTH_MAX*3]; + char buf[HASH_LENGTH_MAX*2 + 1]; /* MAX buf MD_i as a hex string */ + + for (j=0; j<100; j++) { + /* MD_0 = MD_1 = MD_2 = seed */ + memcpy(MD_i3, seed, MDLen); + memcpy(MD_i2, seed, MDLen); + memcpy(MD_i1, seed, MDLen); + + for (i=3; i < 1003; i++) { + /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */ + memcpy(msg, MD_i3, MDLen); + memcpy(&msg[MDLen], MD_i2, MDLen); + memcpy(&msg[MDLen*2], MD_i1,MDLen); + + /* MDi = SHA(Msg) */ + if (sha_calcMD(MD_i, MDLen, + msg, msgLen) != SECSuccess) { + return SECFailure; + } + + /* save MD[i-3] MD[i-2] MD[i-1] */ + memcpy(MD_i3, MD_i2, MDLen); + memcpy(MD_i2, MD_i1, MDLen); + memcpy(MD_i1, MD_i, MDLen); + + } + + /* seed = MD_i */ + memcpy(seed, MD_i, MDLen); + + sprintf(buf, "COUNT = %d\n", j); + fputs(buf, resp); + + /* output MD_i */ + fputs("MD = ", resp); + to_hex_str(buf, MD_i, MDLen); + fputs(buf, resp); + fputc('\n', resp); + } + + return SECSuccess; +} + +/* + * Perform the SHA Tests. + * + * reqfn is the pathname of the input REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void sha_test(char *reqfn) +{ + unsigned int i, j; + unsigned int MDlen; /* the length of the Message Digest in Bytes */ + unsigned int msgLen; /* the length of the input Message in Bytes */ + unsigned char *msg = NULL; /* holds the message to digest.*/ + size_t bufSize = 25608; /*MAX buffer size */ + char *buf = NULL; /* holds one line from the input REQUEST file.*/ + unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */ + unsigned char MD[HASH_LENGTH_MAX]; /* message digest */ + + FILE *req; /* input stream from the REQUEST file */ + FILE *resp; /* output stream to the RESPONSE file */ + + buf = PORT_ZAlloc(bufSize); + if (buf == NULL) { + goto loser; + } + + /* zeroize the variables for the test with this data set */ + memset(seed, 0, sizeof seed); + + req = fopen(reqfn, "r"); + resp = stdout; + while (fgets(buf, bufSize, req) != NULL) { + + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, resp); + continue; + } + /* [L = Length of the Message Digest and sha_type */ + if (buf[0] == '[') { + if (strncmp(&buf[1], "L ", 1) == 0) { + i = 2; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + MDlen = atoi(&buf[i]); + fputs(buf, resp); + continue; + } + } + /* Len = Length of the Input Message Length ... */ + if (strncmp(buf, "Len", 3) == 0) { + i = 3; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + if (msg) { + PORT_ZFree(msg,msgLen); + msg = NULL; + } + msgLen = atoi(&buf[i]); /* in bits */ + msgLen = msgLen/8; /* convert to bytes */ + fputs(buf, resp); + msg = PORT_ZAlloc(msgLen); + if (msg == NULL && msgLen != 0) { + goto loser; + } + continue; + } + /* MSG = ... */ + if (strncmp(buf, "Msg", 3) == 0) { + i = 3; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j< msgLen; i+=2,j++) { + hex_from_2char(&buf[i], &msg[j]); + } + fputs(buf, resp); + /* calculate the Message Digest */ + memset(MD, 0, sizeof MD); + if (sha_calcMD(MD, MDlen, + msg, msgLen) != SECSuccess) { + goto loser; + } + + fputs("MD = ", resp); + to_hex_str(buf, MD, MDlen); + fputs(buf, resp); + fputc('\n', resp); + + continue; + } + /* Seed = ... */ + if (strncmp(buf, "Seed", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j<sizeof seed; i+=2,j++) { + hex_from_2char(&buf[i], &seed[j]); + } + + fputs(buf, resp); + fputc('\n', resp); + + /* do the Monte Carlo test */ + if (sha_mct_test(MDlen, seed, resp) != SECSuccess) { + goto loser; + } + + continue; + } + } +loser: fclose(req); - fclose(rsp); + if (buf) { + PORT_ZFree(buf, bufSize); + } + if (msg) { + PORT_ZFree(msg, msgLen); + } } -void do_random() +/****************************************************/ +/* HMAC SHA-X calc */ +/* hmac_computed - the computed HMAC */ +/* hmac_length - the length of the computed HMAC */ +/* secret_key - secret key to HMAC */ +/* secret_key_length - length of secret key, */ +/* message - message to HMAC */ +/* message_length - length ofthe message */ +/****************************************************/ +static SECStatus +hmac_calc(unsigned char *hmac_computed, + const unsigned int hmac_length, + const unsigned char *secret_key, + const unsigned int secret_key_length, + const unsigned char *message, + const unsigned int message_length, + const HASH_HashType hashAlg ) { - int i, j, k = 0; - unsigned char buf[500]; - for (i=0; i<5; i++) { - RNG_GenerateGlobalRandomBytes(buf, sizeof buf); - for (j=0; j<sizeof buf / 2; j++) { - printf("0x%02x%02x", buf[2*j], buf[2*j+1]); - if (++k % 8 == 0) printf("\n"); else printf(" "); - } + SECStatus hmac_status = SECFailure; + HMACContext *cx = NULL; + SECHashObject *hashObj = NULL; + unsigned int bytes_hashed = 0; + + hashObj = (SECHashObject *) HASH_GetRawHashObject(hashAlg); + + if (!hashObj) + return( SECFailure ); + + cx = HMAC_Create(hashObj, secret_key, + secret_key_length, + PR_TRUE); /* PR_TRUE for in FIPS mode */ + + if (cx == NULL) + return( SECFailure ); + + HMAC_Begin(cx); + HMAC_Update(cx, message, message_length); + hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed, + hmac_length); + + HMAC_Destroy(cx, PR_TRUE); + + return( hmac_status ); +} + +/* + * Perform the HMAC Tests. + * + * reqfn is the pathname of the input REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void hmac_test(char *reqfn) +{ + unsigned int i, j; + size_t bufSize = 288; /* MAX buffer size */ + char *buf = NULL; /* holds one line from the input REQUEST file.*/ + unsigned int keyLen; /* Key Length */ + unsigned char key[140]; /* key MAX size = 140 */ + unsigned int msgLen = 128; /* the length of the input */ + /* Message is always 128 Bytes */ + unsigned char *msg = NULL; /* holds the message to digest.*/ + unsigned int HMACLen; /* the length of the HMAC Bytes */ + unsigned char HMAC[HASH_LENGTH_MAX]; /* computed HMAC */ + HASH_HashType hash_alg; /* HMAC type */ + + FILE *req; /* input stream from the REQUEST file */ + FILE *resp; /* output stream to the RESPONSE file */ + + buf = PORT_ZAlloc(bufSize); + if (buf == NULL) { + goto loser; + } + msg = PORT_ZAlloc(msgLen); + memset(msg, 0, msgLen); + if (msg == NULL) { + goto loser; + } + + req = fopen(reqfn, "r"); + resp = stdout; + while (fgets(buf, bufSize, req) != NULL) { + + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, resp); + continue; + } + /* [L = Length of the MAC and HASH_type */ + if (buf[0] == '[') { + if (strncmp(&buf[1], "L ", 1) == 0) { + i = 2; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + /* HMACLen will get reused for Tlen */ + HMACLen = atoi(&buf[i]); + /* set the HASH algorithm for HMAC */ + if (HMACLen == SHA1_LENGTH) { + hash_alg = HASH_AlgSHA1; + } else if (HMACLen == SHA256_LENGTH) { + hash_alg = HASH_AlgSHA256; + } else if (HMACLen == SHA384_LENGTH) { + hash_alg = HASH_AlgSHA384; + } else if (HMACLen == SHA512_LENGTH) { + hash_alg = HASH_AlgSHA512; + } else { + goto loser; + } + fputs(buf, resp); + continue; + } + } + /* Count = test iteration number*/ + if (strncmp(buf, "Count ", 5) == 0) { + /* count can just be put into resp file */ + fputs(buf, resp); + /* zeroize the variables for the test with this data set */ + keyLen = 0; + HMACLen = 0; + memset(key, 0, sizeof key); + memset(msg, 0, sizeof msg); + memset(HMAC, 0, sizeof HMAC); + continue; + } + /* KLen = Length of the Input Secret Key ... */ + if (strncmp(buf, "Klen", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + keyLen = atoi(&buf[i]); /* in bytes */ + fputs(buf, resp); + continue; + } + /* key = the secret key for the key to MAC */ + if (strncmp(buf, "Key", 3) == 0) { + i = 3; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j< keyLen; i+=2,j++) { + hex_from_2char(&buf[i], &key[j]); + } + fputs(buf, resp); + } + /* TLen = Length of the calculated HMAC */ + if (strncmp(buf, "Tlen", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + HMACLen = atoi(&buf[i]); /* in bytes */ + fputs(buf, resp); + continue; + } + /* MSG = to HMAC always 128 bytes for these tests */ + if (strncmp(buf, "Msg", 3) == 0) { + i = 3; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j< msgLen; i+=2,j++) { + hex_from_2char(&buf[i], &msg[j]); + } + fputs(buf, resp); + /* calculate the HMAC and output */ + if (hmac_calc(HMAC, HMACLen, key, keyLen, + msg, msgLen, hash_alg) != SECSuccess) { + goto loser; + } + fputs("MAC = ", resp); + to_hex_str(buf, HMAC, HMACLen); + fputs(buf, resp); + fputc('\n', resp); + continue; + } + } +loser: + fclose(req); + if (buf) { + PORT_ZFree(buf, bufSize); + } + if (msg) { + PORT_ZFree(msg, msgLen); + } +} + +/* + * Perform the DSA Key Pair Generation Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +dsa_keypair_test(char *reqfn) +{ + char buf[260]; /* holds one line from the input REQUEST file + * or to the output RESPONSE file. + * 257 to hold (128 public key (x2 for HEX) + 1'\n' + */ + FILE *dsareq; /* input stream from the REQUEST file */ + FILE *dsaresp; /* output stream to the RESPONSE file */ + int N; /* number of time to generate key pair */ + int modulus; + int i; + PQGParams *pqg = NULL; + PQGVerify *vfy = NULL; + int keySizeIndex; /* index for valid key sizes */ + + dsareq = fopen(reqfn, "r"); + dsaresp = stdout; + while (fgets(buf, sizeof buf, dsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, dsaresp); + continue; + } + + /* [Mod = x] */ + if (buf[0] == '[') { + if(pqg!=NULL) { + PQG_DestroyParams(pqg); + pqg = NULL; + } + if(vfy!=NULL) { + PQG_DestroyVerify(vfy); + vfy = NULL; + } + + if (sscanf(buf, "[mod = %d]", &modulus) != 1) { + goto loser; + } + fputs(buf, dsaresp); + fputc('\n', dsaresp); + + /***************************************************************** + * PQG_ParamGenSeedLen doesn't take a key size, it takes an index + * that points to a valid key size. + */ + keySizeIndex = PQG_PBITS_TO_INDEX(modulus); + if(keySizeIndex == -1 || modulus<512 || modulus>1024) { + fprintf(dsaresp, + "DSA key size must be a multiple of 64 between 512 " + "and 1024, inclusive"); + goto loser; + } + + /* Generate the parameters P, Q, and G */ + if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES, + &pqg, &vfy) != SECSuccess) { + fprintf(dsaresp, "ERROR: Unable to generate PQG parameters"); + goto loser; + } + + /* output P, Q, and G */ + to_hex_str(buf, pqg->prime.data, pqg->prime.len); + fprintf(dsaresp, "P = %s\n", buf); + to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len); + fprintf(dsaresp, "Q = %s\n", buf); + to_hex_str(buf, pqg->base.data, pqg->base.len); + fprintf(dsaresp, "G = %s\n\n", buf); + continue; + } + /* N = ...*/ + if (buf[0] == 'N') { + + if (sscanf(buf, "N = %d", &N) != 1) { + goto loser; + } + /* Generate a DSA key, and output the key pair for N times */ + for (i = 0; i < N; i++) { + DSAPrivateKey *dsakey = NULL; + if (DSA_NewKey(pqg, &dsakey) != SECSuccess) { + fprintf(dsaresp, "ERROR: Unable to generate DSA key"); + goto loser; + } + to_hex_str(buf, dsakey->privateValue.data, + dsakey->privateValue.len); + fprintf(dsaresp, "X = %s\n", buf); + to_hex_str(buf, dsakey->publicValue.data, + dsakey->publicValue.len); + fprintf(dsaresp, "Y = %s\n\n", buf); + PORT_FreeArena(dsakey->params.arena, PR_TRUE); + dsakey = NULL; + } + continue; + } + + } +loser: + fclose(dsareq); +} + +/* + * Perform the DSA Domain Parameter Validation Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +dsa_pqgver_test(char *reqfn) +{ + char buf[263]; /* holds one line from the input REQUEST file + * or to the output RESPONSE file. + * 260 to hold (128 public key (x2 for HEX) + P = ... + */ + FILE *dsareq; /* input stream from the REQUEST file */ + FILE *dsaresp; /* output stream to the RESPONSE file */ + int modulus; + unsigned int i, j; + PQGParams pqg; + PQGVerify vfy; + unsigned int pghSize; /* size for p, g, and h */ + + dsareq = fopen(reqfn, "r"); + dsaresp = stdout; + memset(&pqg, 0, sizeof(pqg)); + memset(&vfy, 0, sizeof(vfy)); + + while (fgets(buf, sizeof buf, dsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, dsaresp); + continue; + } + + /* [Mod = x] */ + if (buf[0] == '[') { + + if (sscanf(buf, "[mod = %d]", &modulus) != 1) { + goto loser; + } + + if (pqg.prime.data) { /* P */ + SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); + } + if (pqg.subPrime.data) { /* Q */ + SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); + } + if (pqg.base.data) { /* G */ + SECITEM_ZfreeItem(&pqg.base, PR_FALSE); + } + if (vfy.seed.data) { /* seed */ + SECITEM_ZfreeItem(&vfy.seed, PR_FALSE); + } + if (vfy.h.data) { /* H */ + SECITEM_ZfreeItem(&vfy.h, PR_FALSE); + } + + fputs(buf, dsaresp); + + /*calculate the size of p, g, and h then allocate items */ + pghSize = modulus/8; + SECITEM_AllocItem(NULL, &pqg.prime, pghSize); + SECITEM_AllocItem(NULL, &pqg.base, pghSize); + SECITEM_AllocItem(NULL, &vfy.h, pghSize); + pqg.prime.len = pqg.base.len = vfy.h.len = pghSize; + /* seed and q are always 20 bytes */ + SECITEM_AllocItem(NULL, &vfy.seed, 20); + SECITEM_AllocItem(NULL, &pqg.subPrime, 20); + vfy.seed.len = pqg.subPrime.len = 20; + vfy.counter = 0; + + continue; + } + /* P = ... */ + if (buf[0] == 'P') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j< pqg.prime.len; i+=2,j++) { + hex_from_2char(&buf[i], &pqg.prime.data[j]); + } + + fputs(buf, dsaresp); + continue; + } + + /* Q = ... */ + if (buf[0] == 'Q') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j< pqg.subPrime.len; i+=2,j++) { + hex_from_2char(&buf[i], &pqg.subPrime.data[j]); + } + + fputs(buf, dsaresp); + continue; + } + + /* G = ... */ + if (buf[0] == 'G') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j< pqg.base.len; i+=2,j++) { + hex_from_2char(&buf[i], &pqg.base.data[j]); + } + + fputs(buf, dsaresp); + continue; + } + + /* Seed = ... */ + if (strncmp(buf, "Seed", 4) == 0) { + i = 4; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j< vfy.seed.len; i+=2,j++) { + hex_from_2char(&buf[i], &vfy.seed.data[j]); + } + + fputs(buf, dsaresp); + continue; + } + + /* c = ... */ + if (buf[0] == 'c') { + + if (sscanf(buf, "c = %u", &vfy.counter) != 1) { + goto loser; + } + + fputs(buf, dsaresp); + continue; + } + + /* H = ... */ + if (buf[0] == 'H') { + SECStatus rv, result = SECFailure; + + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j< vfy.h.len; i+=2,j++) { + hex_from_2char(&buf[i], &vfy.h.data[j]); + } + fputs(buf, dsaresp); + + /* Verify the Parameters */ + rv = PQG_VerifyParams(&pqg, &vfy, &result); + if (rv != SECSuccess) { + goto loser; + } + if (result == SECSuccess) { + fprintf(dsaresp, "Result = P\n"); + } else { + fprintf(dsaresp, "Result = F\n"); + } + continue; + } + } +loser: + fclose(dsareq); + if (pqg.prime.data) { /* P */ + SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); + } + if (pqg.subPrime.data) { /* Q */ + SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); + } + if (pqg.base.data) { /* G */ + SECITEM_ZfreeItem(&pqg.base, PR_FALSE); + } + if (vfy.seed.data) { /* seed */ + SECITEM_ZfreeItem(&vfy.seed, PR_FALSE); + } + if (vfy.h.data) { /* H */ + SECITEM_ZfreeItem(&vfy.h, PR_FALSE); + } + +} + +/* + * Perform the DSA Public Key Validation Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +dsa_pqggen_test(char *reqfn) +{ + char buf[263]; /* holds one line from the input REQUEST file + * or to the output RESPONSE file. + * 263 to hold seed = (128 public key (x2 for HEX) + */ + FILE *dsareq; /* input stream from the REQUEST file */ + FILE *dsaresp; /* output stream to the RESPONSE file */ + int N; /* number of times to generate parameters */ + int modulus; + int i; + unsigned int j; + PQGParams *pqg = NULL; + PQGVerify *vfy = NULL; + unsigned int keySizeIndex; + + dsareq = fopen(reqfn, "r"); + dsaresp = stdout; + while (fgets(buf, sizeof buf, dsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, dsaresp); + continue; + } + + /* [Mod = ... ] */ + if (buf[0] == '[') { + + if (sscanf(buf, "[mod = %d]", &modulus) != 1) { + goto loser; + } + + fputs(buf, dsaresp); + fputc('\n', dsaresp); + + /**************************************************************** + * PQG_ParamGenSeedLen doesn't take a key size, it takes an index + * that points to a valid key size. + */ + keySizeIndex = PQG_PBITS_TO_INDEX(modulus); + if(keySizeIndex == -1 || modulus<512 || modulus>1024) { + fprintf(dsaresp, + "DSA key size must be a multiple of 64 between 512 " + "and 1024, inclusive"); + goto loser; + } + + continue; + } + /* N = ... */ + if (buf[0] == 'N') { + + if (sscanf(buf, "N = %d", &N) != 1) { + goto loser; + } + for (i = 0; i < N; i++) { + if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES, + &pqg, &vfy) != SECSuccess) { + fprintf(dsaresp, + "ERROR: Unable to generate PQG parameters"); + goto loser; + } + to_hex_str(buf, pqg->prime.data, pqg->prime.len); + fprintf(dsaresp, "P = %s\n", buf); + to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len); + fprintf(dsaresp, "Q = %s\n", buf); + to_hex_str(buf, pqg->base.data, pqg->base.len); + fprintf(dsaresp, "G = %s\n", buf); + to_hex_str(buf, vfy->seed.data, vfy->seed.len); + fprintf(dsaresp, "Seed = %s\n", buf); + fprintf(dsaresp, "c = %d\n", vfy->counter); + to_hex_str(buf, vfy->h.data, vfy->h.len); + fputs("H = ", dsaresp); + for (j=vfy->h.len; j<pqg->prime.len; j++) { + fprintf(dsaresp, "00"); + } + fprintf(dsaresp, "%s\n", buf); + fputc('\n', dsaresp); + if(pqg!=NULL) { + PQG_DestroyParams(pqg); + pqg = NULL; + } + if(vfy!=NULL) { + PQG_DestroyVerify(vfy); + vfy = NULL; + } + } + + continue; + } + + } +loser: + fclose(dsareq); + if(pqg!=NULL) { + PQG_DestroyParams(pqg); + } + if(vfy!=NULL) { + PQG_DestroyVerify(vfy); + } +} + +/* + * Perform the DSA Signature Generation Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +dsa_siggen_test(char *reqfn) +{ + char buf[263]; /* holds one line from the input REQUEST file + * or to the output RESPONSE file. + * max for Msg = .... + */ + FILE *dsareq; /* input stream from the REQUEST file */ + FILE *dsaresp; /* output stream to the RESPONSE file */ + int modulus; + int i, j; + PQGParams *pqg = NULL; + PQGVerify *vfy = NULL; + DSAPrivateKey *dsakey = NULL; + int keySizeIndex; /* index for valid key sizes */ + unsigned char sha1[20]; /* SHA-1 hash (160 bits) */ + unsigned char sig[DSA_SIGNATURE_LEN]; + SECItem digest, signature; + + dsareq = fopen(reqfn, "r"); + dsaresp = stdout; + + while (fgets(buf, sizeof buf, dsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, dsaresp); + continue; + } + + /* [Mod = x] */ + if (buf[0] == '[') { + if(pqg!=NULL) { + PQG_DestroyParams(pqg); + pqg = NULL; + } + if(vfy!=NULL) { + PQG_DestroyVerify(vfy); + vfy = NULL; + } + if (dsakey != NULL) { + PORT_FreeArena(dsakey->params.arena, PR_TRUE); + dsakey = NULL; + } + + if (sscanf(buf, "[mod = %d]", &modulus) != 1) { + goto loser; + } + fputs(buf, dsaresp); + fputc('\n', dsaresp); + + /**************************************************************** + * PQG_ParamGenSeedLen doesn't take a key size, it takes an index + * that points to a valid key size. + */ + keySizeIndex = PQG_PBITS_TO_INDEX(modulus); + if(keySizeIndex == -1 || modulus<512 || modulus>1024) { + fprintf(dsaresp, + "DSA key size must be a multiple of 64 between 512 " + "and 1024, inclusive"); + goto loser; + } + + /* Generate PQG and output PQG */ + if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES, + &pqg, &vfy) != SECSuccess) { + fprintf(dsaresp, "ERROR: Unable to generate PQG parameters"); + goto loser; + } + to_hex_str(buf, pqg->prime.data, pqg->prime.len); + fprintf(dsaresp, "P = %s\n", buf); + to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len); + fprintf(dsaresp, "Q = %s\n", buf); + to_hex_str(buf, pqg->base.data, pqg->base.len); + fprintf(dsaresp, "G = %s\n", buf); + + /* create DSA Key */ + if (DSA_NewKey(pqg, &dsakey) != SECSuccess) { + fprintf(dsaresp, "ERROR: Unable to generate DSA key"); + goto loser; + } + continue; + } + + /* Msg = ... */ + if (strncmp(buf, "Msg", 3) == 0) { + unsigned char msg[128]; /* MAX msg 128 */ + unsigned int len = 0; + + memset(sha1, 0, sizeof sha1); + memset(sig, 0, sizeof sig); + + i = 3; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &msg[j]); + } + if (SHA1_HashBuf(sha1, msg, j) != SECSuccess) { + fprintf(dsaresp, "ERROR: Unable to generate SHA1 digest"); + goto loser; + } + + digest.type = siBuffer; + digest.data = sha1; + digest.len = sizeof sha1; + signature.type = siBuffer; + signature.data = sig; + signature.len = sizeof sig; + + if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) { + fprintf(dsaresp, "ERROR: Unable to generate DSA signature"); + goto loser; + } + len = signature.len; + if (len%2 != 0) { + goto loser; + } + len = len/2; + + /* output the orginal Msg, and generated Y, R, and S */ + fputs(buf, dsaresp); + fputc('\n', dsaresp); + to_hex_str(buf, dsakey->publicValue.data, + dsakey->publicValue.len); + fprintf(dsaresp, "Y = %s\n", buf); + to_hex_str(buf, &signature.data[0], len); + fprintf(dsaresp, "R = %s\n", buf); + to_hex_str(buf, &signature.data[len], len); + fprintf(dsaresp, "S = %s\n", buf); + continue; + } + + } +loser: + fclose(dsareq); + if(pqg != NULL) { + PQG_DestroyParams(pqg); + pqg = NULL; + } + if(vfy != NULL) { + PQG_DestroyVerify(vfy); + vfy = NULL; + } + if (dsaKey) { + PORT_FreeArena(dsakey->params.arena, PR_TRUE); + dsakey = NULL; + } +} + + /* + * Perform the DSA Signature Verification Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +dsa_sigver_test(char *reqfn) +{ + char buf[263]; /* holds one line from the input REQUEST file + * or to the output RESPONSE file. + * max for Msg = .... + */ + FILE *dsareq; /* input stream from the REQUEST file */ + FILE *dsaresp; /* output stream to the RESPONSE file */ + int modulus; + unsigned int i, j; + SECItem digest, signature; + DSAPublicKey pubkey; + unsigned int pgySize; /* size for p, g, and y */ + unsigned char sha1[20]; /* SHA-1 hash (160 bits) */ + unsigned char sig[DSA_SIGNATURE_LEN]; + + dsareq = fopen(reqfn, "r"); + dsaresp = stdout; + memset(&pubkey, 0, sizeof(pubkey)); + + while (fgets(buf, sizeof buf, dsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, dsaresp); + continue; + } + + /* [Mod = x] */ + if (buf[0] == '[') { + + if (sscanf(buf, "[mod = %d]", &modulus) != 1) { + goto loser; + } + + if (pubkey.params.prime.data) { /* P */ + SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE); + } + if (pubkey.params.subPrime.data) { /* Q */ + SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE); + } + if (pubkey.params.base.data) { /* G */ + SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE); + } + if (pubkey.publicValue.data) { /* Y */ + SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE); + } + fputs(buf, dsaresp); + + /* calculate the size of p, g, and y then allocate items */ + pgySize = modulus/8; + SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize); + SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize); + SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize); + pubkey.params.prime.len = pubkey.params.base.len = pgySize; + pubkey.publicValue.len = pgySize; + + /* q always 20 bytes */ + SECITEM_AllocItem(NULL, &pubkey.params.subPrime, 20); + pubkey.params.subPrime.len = 20; + + continue; + } + /* P = ... */ + if (buf[0] == 'P') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + memset(pubkey.params.prime.data, 0, pubkey.params.prime.len); + for (j=0; j< pubkey.params.prime.len; i+=2,j++) { + hex_from_2char(&buf[i], &pubkey.params.prime.data[j]); + } + + fputs(buf, dsaresp); + continue; + } + + /* Q = ... */ + if (buf[0] == 'Q') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len); + for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) { + hex_from_2char(&buf[i], &pubkey.params.subPrime.data[j]); + } + + fputs(buf, dsaresp); + continue; + } + + /* G = ... */ + if (buf[0] == 'G') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + memset(pubkey.params.base.data, 0, pubkey.params.base.len); + for (j=0; j< pubkey.params.base.len; i+=2,j++) { + hex_from_2char(&buf[i], &pubkey.params.base.data[j]); + } + + fputs(buf, dsaresp); + continue; + } + + /* Msg = ... */ + if (strncmp(buf, "Msg", 3) == 0) { + unsigned char msg[128]; /* MAX msg 128 */ + memset(sha1, 0, sizeof sha1); + + i = 3; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]); i+=2,j++) { + hex_from_2char(&buf[i], &msg[j]); + } + if (SHA1_HashBuf(sha1, msg, j) != SECSuccess) { + fprintf(dsaresp, "ERROR: Unable to generate SHA1 digest"); + goto loser; + } + + fputs(buf, dsaresp); + continue; + } + + /* Y = ... */ + if (buf[0] == 'Y') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len); + for (j=0; j< pubkey.publicValue.len; i+=2,j++) { + hex_from_2char(&buf[i], &pubkey.publicValue.data[j]); + } + + fputs(buf, dsaresp); + continue; + } + + /* R = ... */ + if (buf[0] == 'R') { + memset(sig, 0, sizeof sig); + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; j< DSA_SUBPRIME_LEN; i+=2,j++) { + hex_from_2char(&buf[i], &sig[j]); + } + + fputs(buf, dsaresp); + continue; + } + + /* S = ... */ + if (buf[0] == 'S') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=DSA_SUBPRIME_LEN; j< DSA_SIGNATURE_LEN; i+=2,j++) { + hex_from_2char(&buf[i], &sig[j]); + } + fputs(buf, dsaresp); + + digest.type = siBuffer; + digest.data = sha1; + digest.len = sizeof sha1; + signature.type = siBuffer; + signature.data = sig; + signature.len = sizeof sig; + + if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) { + fprintf(dsaresp, "Result = P\n"); + } else { + fprintf(dsaresp, "Result = F\n"); + } + continue; + } + } +loser: + fclose(dsareq); + if (pubkey.params.prime.data) { /* P */ + SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE); + } + if (pubkey.params.subPrime.data) { /* Q */ + SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE); + } + if (pubkey.params.base.data) { /* G */ + SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE); + } + if (pubkey.publicValue.data) { /* Y */ + SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE); + } +} + +/* + * Perform the RSA Signature Generation Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +rsa_siggen_test(char *reqfn) +{ + char buf[2*RSA_MAX_TEST_MODULUS_BYTES+1]; + /* buf holds one line from the input REQUEST file + * or to the output RESPONSE file. + * 2x for HEX output + 1 for \n + */ + FILE *rsareq; /* input stream from the REQUEST file */ + FILE *rsaresp; /* output stream to the RESPONSE file */ + int i, j; + unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */ + unsigned int shaLength = 0; /* length of SHA */ + HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */ + SECOidTag shaOid = SEC_OID_UNKNOWN; + int modulus; /* the Modulus size */ + int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT; + SECItem pe = {0, 0, 0 }; + unsigned char pubEx[4]; + int peCount = 0; + + RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and + * public keys */ + RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */ + + rsareq = fopen(reqfn, "r"); + rsaresp = stdout; + + /* calculate the exponent */ + for (i=0; i < 4; i++) { + if (peCount || (publicExponent & + ((unsigned long)0xff000000L >> (i*8)))) { + pubEx[peCount] = + (unsigned char)((publicExponent >> (3-i)*8) & 0xff); + peCount++; + } + } + pe.len = peCount; + pe.data = &pubEx[0]; + pe.type = siBuffer; + + while (fgets(buf, sizeof buf, rsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, rsaresp); + continue; + } + + /* [mod = ...] */ + if (buf[0] == '[') { + + if (sscanf(buf, "[mod = %d]", &modulus) != 1) { + goto loser; + } + if (modulus > RSA_MAX_TEST_MODULUS_BITS) { + fprintf(rsaresp,"ERROR: modulus greater than test maximum\n"); + goto loser; + } + + fputs(buf, rsaresp); + + if (rsaBlapiPrivKey != NULL) { + PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE); + rsaBlapiPrivKey = NULL; + rsaBlapiPublicKey = NULL; + } + + rsaBlapiPrivKey = RSA_NewKey(modulus, &pe); + if (rsaBlapiPrivKey == NULL) { + fprintf(rsaresp, "Error unable to create RSA key\n"); + goto loser; + } + + to_hex_str(buf, rsaBlapiPrivKey->modulus.data, + rsaBlapiPrivKey->modulus.len); + fprintf(rsaresp, "\nn = %s\n\n", buf); + to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data, + rsaBlapiPrivKey->publicExponent.len); + fprintf(rsaresp, "e = %s\n", buf); + /* convert private key to public key. Memory + * is freed with private key's arena */ + rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc( + rsaBlapiPrivKey->arena, + sizeof(RSAPublicKey)); + + rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len; + rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data; + rsaBlapiPublicKey->publicExponent.len = + rsaBlapiPrivKey->publicExponent.len; + rsaBlapiPublicKey->publicExponent.data = + rsaBlapiPrivKey->publicExponent.data; + continue; + } + + /* SHAAlg = ... */ + if (strncmp(buf, "SHAAlg", 6) == 0) { + i = 6; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + /* set the SHA Algorithm */ + if (strncmp(&buf[i], "SHA1", 4) == 0) { + shaAlg = HASH_AlgSHA1; + } else if (strncmp(&buf[i], "SHA256", 6) == 0) { + shaAlg = HASH_AlgSHA256; + } else if (strncmp(&buf[i], "SHA384", 6)== 0) { + shaAlg = HASH_AlgSHA384; + } else if (strncmp(&buf[i], "SHA512", 6) == 0) { + shaAlg = HASH_AlgSHA512; + } else { + fprintf(rsaresp, "ERROR: Unable to find SHAAlg type"); + goto loser; + } + fputs(buf, rsaresp); + continue; + + } + /* Msg = ... */ + if (strncmp(buf, "Msg", 3) == 0) { + + unsigned char msg[128]; /* MAX msg 128 */ + unsigned int rsa_bytes_signed; + unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES]; + SECStatus rv = SECFailure; + NSSLOWKEYPublicKey * rsa_public_key; + NSSLOWKEYPrivateKey * rsa_private_key; + NSSLOWKEYPrivateKey low_RSA_private_key = { NULL, + NSSLOWKEYRSAKey, }; + NSSLOWKEYPublicKey low_RSA_public_key = { NULL, + NSSLOWKEYRSAKey, }; + + low_RSA_private_key.u.rsa = *rsaBlapiPrivKey; + low_RSA_public_key.u.rsa = *rsaBlapiPublicKey; + + rsa_private_key = &low_RSA_private_key; + rsa_public_key = &low_RSA_public_key; + + memset(sha, 0, sizeof sha); + memset(msg, 0, sizeof msg); + rsa_bytes_signed = 0; + memset(rsa_computed_signature, 0, sizeof rsa_computed_signature); + + i = 3; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + for (j=0; isxdigit(buf[i]) && j < sizeof(msg); i+=2,j++) { + hex_from_2char(&buf[i], &msg[j]); + } + + if (shaAlg == HASH_AlgSHA1) { + if (SHA1_HashBuf(sha, msg, j) != SECSuccess) { + fprintf(rsaresp, "ERROR: Unable to generate SHA1"); + goto loser; + } + shaLength = SHA1_LENGTH; + shaOid = SEC_OID_SHA1; + } else if (shaAlg == HASH_AlgSHA256) { + if (SHA256_HashBuf(sha, msg, j) != SECSuccess) { + fprintf(rsaresp, "ERROR: Unable to generate SHA256"); + goto loser; + } + shaLength = SHA256_LENGTH; + shaOid = SEC_OID_SHA256; + } else if (shaAlg == HASH_AlgSHA384) { + if (SHA384_HashBuf(sha, msg, j) != SECSuccess) { + fprintf(rsaresp, "ERROR: Unable to generate SHA384"); + goto loser; + } + shaLength = SHA384_LENGTH; + shaOid = SEC_OID_SHA384; + } else if (shaAlg == HASH_AlgSHA512) { + if (SHA512_HashBuf(sha, msg, j) != SECSuccess) { + fprintf(rsaresp, "ERROR: Unable to generate SHA512"); + goto loser; + } + shaLength = SHA512_LENGTH; + shaOid = SEC_OID_SHA512; + } else { + fprintf(rsaresp, "ERROR: SHAAlg not defined."); + goto loser; + } + + /* Perform RSA signature with the RSA private key. */ + rv = RSA_HashSign( shaOid, + rsa_private_key, + rsa_computed_signature, + &rsa_bytes_signed, + nsslowkey_PrivateModulusLen(rsa_private_key), + sha, + shaLength); + + if( rv != SECSuccess ) { + fprintf(rsaresp, "ERROR: RSA_HashSign failed"); + goto loser; + } + + /* Output the signature */ + fputs(buf, rsaresp); + to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed); + fprintf(rsaresp, "S = %s\n", buf); + + /* Perform RSA verification with the RSA public key. */ + rv = RSA_HashCheckSign( shaOid, + rsa_public_key, + rsa_computed_signature, + rsa_bytes_signed, + sha, + shaLength); + if( rv != SECSuccess ) { + fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed"); + goto loser; + } + continue; + } + } +loser: + fclose(rsareq); + + if (rsaBlapiPrivKey != NULL) { + /* frees private and public key */ + PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE); + rsaBlapiPrivKey = NULL; + rsaBlapiPublicKey = NULL; + } + +} +/* + * Perform the RSA Signature Verification Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ +void +rsa_sigver_test(char *reqfn) +{ + char buf[2*RSA_MAX_TEST_MODULUS_BYTES+7]; + /* buf holds one line from the input REQUEST file + * or to the output RESPONSE file. + * s = 2x for HEX output + 1 for \n + */ + FILE *rsareq; /* input stream from the REQUEST file */ + FILE *rsaresp; /* output stream to the RESPONSE file */ + int i, j; + unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */ + unsigned int shaLength = 0; /* actual length of the digest */ + HASH_HashType shaAlg = HASH_AlgNULL; + SECOidTag shaOid = SEC_OID_UNKNOWN; + int modulus = 0; /* the Modulus size */ + unsigned char signature[513]; /* largest signature size + '\n' */ + unsigned int signatureLength = 0; /* actual length of the signature */ + PRBool keyvalid = PR_TRUE; + + RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */ + + rsareq = fopen(reqfn, "r"); + rsaresp = stdout; + memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey)); + + while (fgets(buf, sizeof buf, rsareq) != NULL) { + /* a comment or blank line */ + if (buf[0] == '#' || buf[0] == '\n') { + fputs(buf, rsaresp); + continue; + } + + /* [Mod = ...] */ + if (buf[0] == '[') { + unsigned int flen; /* length in bytes of the field size */ + + if (rsaBlapiPublicKey.modulus.data) { /* n */ + SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE); + } + if (sscanf(buf, "[mod = %d]", &modulus) != 1) { + goto loser; + } + + if (modulus > RSA_MAX_TEST_MODULUS_BITS) { + fprintf(rsaresp,"ERROR: modulus greater than test maximum\n"); + goto loser; + } + + fputs(buf, rsaresp); + + signatureLength = flen = modulus/8; + + SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen); + if (rsaBlapiPublicKey.modulus.data == NULL) { + goto loser; + } + continue; + } + + /* n = ... modulus */ + if (buf[0] == 'n') { + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0], + rsaBlapiPublicKey.modulus.len, + &buf[i]); + + if (!keyvalid) { + fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n"); + goto loser; + } + fputs(buf, rsaresp); + continue; + } + + /* SHAAlg = ... */ + if (strncmp(buf, "SHAAlg", 6) == 0) { + i = 6; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + /* set the SHA Algorithm */ + if (strncmp(&buf[i], "SHA1", 4) == 0) { + shaAlg = HASH_AlgSHA1; + } else if (strncmp(&buf[i], "SHA256", 6) == 0) { + shaAlg = HASH_AlgSHA256; + } else if (strncmp(&buf[i], "SHA384", 6) == 0) { + shaAlg = HASH_AlgSHA384; + } else if (strncmp(&buf[i], "SHA512", 6) == 0) { + shaAlg = HASH_AlgSHA512; + } else { + fprintf(rsaresp, "ERROR: Unable to find SHAAlg type"); + goto loser; + } + fputs(buf, rsaresp); + continue; + } + + /* e = ... public Key */ + if (buf[0] == 'e') { + unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES]; + unsigned char t; + + memset(data, 0, sizeof data); + + if (rsaBlapiPublicKey.publicExponent.data) { /* e */ + SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE); + } + + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + /* skip leading zero's */ + while (isxdigit(buf[i])) { + hex_from_2char(&buf[i], &t); + if (t == 0) { + i+=2; + } else break; + } + + /* get the exponent */ + for (j=0; isxdigit(buf[i]) && j < sizeof data; i+=2,j++) { + hex_from_2char(&buf[i], &data[j]); + } + + if (j == 0) { j = 1; } /* to handle 1 byte length exponents */ + + SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j); + if (rsaBlapiPublicKey.publicExponent.data == NULL) { + goto loser; + } + + for (i=0; i < j; i++) { + rsaBlapiPublicKey.publicExponent.data[i] = data[i]; + } + + fputs(buf, rsaresp); + continue; + } + + /* Msg = ... */ + if (strncmp(buf, "Msg", 3) == 0) { + unsigned char msg[128]; /* MAX msg 128 */ + + memset(sha, 0, sizeof sha); + memset(msg, 0, sizeof msg); + + i = 3; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + + for (j=0; isxdigit(buf[i]) && j < sizeof msg; i+=2,j++) { + hex_from_2char(&buf[i], &msg[j]); + } + + if (shaAlg == HASH_AlgSHA1) { + if (SHA1_HashBuf(sha, msg, j) != SECSuccess) { + fprintf(rsaresp, "ERROR: Unable to generate SHA1"); + goto loser; + } + shaLength = SHA1_LENGTH; + shaOid = SEC_OID_SHA1; + } else if (shaAlg == HASH_AlgSHA256) { + if (SHA256_HashBuf(sha, msg, j) != SECSuccess) { + fprintf(rsaresp, "ERROR: Unable to generate SHA256"); + goto loser; + } + shaLength = SHA256_LENGTH; + shaOid = SEC_OID_SHA256; + } else if (shaAlg == HASH_AlgSHA384) { + if (SHA384_HashBuf(sha, msg, j) != SECSuccess) { + fprintf(rsaresp, "ERROR: Unable to generate SHA384"); + goto loser; + } + shaLength = SHA384_LENGTH; + shaOid = SEC_OID_SHA384; + } else if (shaAlg == HASH_AlgSHA512) { + if (SHA512_HashBuf(sha, msg, j) != SECSuccess) { + fprintf(rsaresp, "ERROR: Unable to generate SHA512"); + goto loser; + } + shaLength = SHA512_LENGTH; + shaOid = SEC_OID_SHA512; + } else { + fprintf(rsaresp, "ERROR: SHAAlg not defined."); + goto loser; + } + + fputs(buf, rsaresp); + continue; + + } + + /* S = ... */ + if (buf[0] == 'S') { + SECStatus rv = SECFailure; + NSSLOWKEYPublicKey * rsa_public_key; + NSSLOWKEYPublicKey low_RSA_public_key = { NULL, + NSSLOWKEYRSAKey, }; + + /* convert to a low RSA public key */ + low_RSA_public_key.u.rsa = rsaBlapiPublicKey; + rsa_public_key = &low_RSA_public_key; + + memset(signature, 0, sizeof(signature)); + i = 1; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + + for (j=0; isxdigit(buf[i]) && j < sizeof signature; i+=2,j++) { + hex_from_2char(&buf[i], &signature[j]); + } + + signatureLength = j; + fputs(buf, rsaresp); + + /* Perform RSA verification with the RSA public key. */ + rv = RSA_HashCheckSign( shaOid, + rsa_public_key, + signature, + signatureLength, + sha, + shaLength); + if( rv == SECSuccess ) { + fputs("Result = P\n", rsaresp); + } else { + fputs("Result = F\n", rsaresp); + } + continue; + } + } +loser: + fclose(rsareq); + if (rsaBlapiPublicKey.modulus.data) { /* n */ + SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE); + } + if (rsaBlapiPublicKey.publicExponent.data) { /* e */ + SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE); } } int main(int argc, char **argv) { - unsigned char key[24]; - unsigned char inp[24]; - unsigned char iv[8]; if (argc < 2) exit (-1); NSS_NoDB_Init(NULL); - memset(inp, 0, sizeof inp); - /*************/ - /* DES */ - /*************/ - /**** ECB ****/ - /* encrypt */ - if ( strcmp(argv[1], "des_5_1_1_1") == 0) { - printf("Variable Plaintext Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - des_var_pt_kat(NSS_DES, PR_TRUE, 8, key, NULL, NULL); - } else if (strcmp(argv[1], "des_5_1_1_2") == 0) { - printf("Inverse Plaintext Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - des_inv_perm_kat(NSS_DES, PR_TRUE, 8, key, NULL, NULL); - } else if (strcmp(argv[1], "des_5_1_1_3") == 0) { - printf("Variable Key Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - des_var_key_kat(NSS_DES, PR_TRUE, 8, key, NULL, inp); - } else if (strcmp(argv[1], "des_5_1_1_4") == 0) { - printf("Permutation Operation Known Answer Test - Encryption\n\n"); - des_perm_op_kat(NSS_DES, PR_TRUE, 8, NULL, NULL, inp); - } else if (strcmp(argv[1], "des_5_1_1_5") == 0) { - printf("Substitution Table Known Answer Test - Encryption\n\n"); - des_sub_tbl_kat(NSS_DES, PR_TRUE, 8, NULL, NULL, NULL); - } else if (strcmp(argv[1], "des_5_1_1_6") == 0) { - printf("Modes Test for the Encryption Process\n\n"); - des_modes(NSS_DES, PR_TRUE, 8, des_ecb_enc_key, - NULL, des_ecb_enc_inp, 0); - /* decrypt */ - } else if (strcmp(argv[1], "des_5_1_2_1") == 0) { - printf("Variable Ciphertext Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - des_var_pt_kat(NSS_DES, PR_FALSE, 8, key, NULL, NULL); - } else if (strcmp(argv[1], "des_5_1_2_2") == 0) { - printf("Inverse Permutation Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - des_inv_perm_kat(NSS_DES, PR_FALSE, 8, key, NULL, NULL); - } else if (strcmp(argv[1], "des_5_1_2_3") == 0) { - printf("Variable Key Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - des_var_key_kat(NSS_DES, PR_FALSE, 8, key, NULL, inp); - } else if (strcmp(argv[1], "des_5_1_2_4") == 0) { - printf("Permutation Operation Known Answer Test - Decryption\n\n"); - des_perm_op_kat(NSS_DES, PR_FALSE, 8, NULL, NULL, inp); - } else if (strcmp(argv[1], "des_5_1_2_5") == 0) { - printf("Substitution Table Known Answer Test - Decryption\n\n"); - des_sub_tbl_kat(NSS_DES, PR_FALSE, 8, NULL, NULL, NULL); - } else if (strcmp(argv[1], "des_5_1_2_6") == 0) { - printf("Modes Test for the Decryption Process\n\n"); - des_modes(NSS_DES, PR_FALSE, 8, des_ecb_dec_key, - NULL, des_ecb_dec_inp, 0); - /**** CBC ****/ - /* encrypt */ - } else if (strcmp(argv[1], "des_5_2_1_1") == 0) { - printf("Variable Plaintext Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_var_pt_kat(NSS_DES_CBC, PR_TRUE, 8, key, iv, NULL); - } else if (strcmp(argv[1], "des_5_2_1_2") == 0) { - printf("Inverse Plaintext Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_inv_perm_kat(NSS_DES_CBC, PR_TRUE, 8, key, iv, NULL); - } else if (strcmp(argv[1], "des_5_2_1_3") == 0) { - printf("Variable Key Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_var_key_kat(NSS_DES_CBC, PR_TRUE, 8, key, iv, inp); - } else if (strcmp(argv[1], "des_5_2_1_4") == 0) { - printf("Permutation Operation Known Answer Test - Encryption\n\n"); - memset(iv, 0, sizeof iv); - des_perm_op_kat(NSS_DES_CBC, PR_TRUE, 8, NULL, iv, inp); - } else if (strcmp(argv[1], "des_5_2_1_5") == 0) { - printf("Substitution Table Known Answer Test - Encryption\n\n"); - memset(iv, 0, sizeof iv); - des_sub_tbl_kat(NSS_DES_CBC, PR_TRUE, 8, NULL, iv, NULL); - } else if (strcmp(argv[1], "des_5_2_1_6") == 0) { - printf("Modes Test for the Encryption Process\n\n"); - des_modes(NSS_DES_CBC, PR_TRUE, 8, des_cbc_enc_key, - des_cbc_enc_iv, des_cbc_enc_inp, 0); - /* decrypt */ - } else if (strcmp(argv[1], "des_5_2_2_1") == 0) { - printf("Variable Ciphertext Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_var_pt_kat(NSS_DES_CBC, PR_FALSE, 8, key, iv, NULL); - } else if (strcmp(argv[1], "des_5_2_2_2") == 0) { - printf("Inverse Permutation Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_inv_perm_kat(NSS_DES_CBC, PR_FALSE, 8, key, iv, NULL); - } else if (strcmp(argv[1], "des_5_2_2_3") == 0) { - printf("Variable Key Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_var_key_kat(NSS_DES_CBC, PR_FALSE, 8, key, iv, inp); - } else if (strcmp(argv[1], "des_5_2_2_4") == 0) { - printf("Permutation Operation Known Answer Test - Decryption\n\n"); - memset(iv, 0, sizeof iv); - des_perm_op_kat(NSS_DES_CBC, PR_FALSE, 8, NULL, iv, inp); - } else if (strcmp(argv[1], "des_5_2_2_5") == 0) { - printf("Substitution Table Known Answer Test - Decryption\n\n"); - memset(iv, 0, sizeof iv); - des_sub_tbl_kat(NSS_DES_CBC, PR_FALSE, 8, NULL, iv, NULL); - } else if (strcmp(argv[1], "des_5_2_2_6") == 0) { - printf("Modes Test for the Decryption Process\n\n"); - des_modes(NSS_DES_CBC, PR_FALSE, 8, des_cbc_dec_key, - des_cbc_dec_iv, des_cbc_dec_inp, 0); /*************/ /* TDEA */ /*************/ - /**** ECB ****/ - /* encrypt */ - } else if (strcmp(argv[1], "tdea_5_1_1_1") == 0) { - printf("Variable Plaintext Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - des_var_pt_kat(NSS_DES_EDE3, PR_TRUE, 24, key, NULL, NULL); - } else if (strcmp(argv[1], "tdea_5_1_1_2") == 0) { - printf("Inverse Plaintext Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - des_inv_perm_kat(NSS_DES_EDE3, PR_TRUE, 24, key, NULL, NULL); - } else if (strcmp(argv[1], "tdea_5_1_1_3") == 0) { - printf("Variable Key Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - des_var_key_kat(NSS_DES_EDE3, PR_TRUE, 24, key, NULL, inp); - } else if (strcmp(argv[1], "tdea_5_1_1_4") == 0) { - printf("Permutation Operation Known Answer Test - Encryption\n\n"); - des_perm_op_kat(NSS_DES_EDE3, PR_TRUE, 24, NULL, NULL, inp); - } else if (strcmp(argv[1], "tdea_5_1_1_5") == 0) { - printf("Substitution Table Known Answer Test - Encryption\n\n"); - des_sub_tbl_kat(NSS_DES_EDE3, PR_TRUE, 24, NULL, NULL, NULL); - } else if (strcmp(argv[1], "tdea_5_1_1_6_3") == 0) { - printf("Modes Test for the Encryption Process\n"); - printf("DATA FILE UTILIZED: datecbmontee1\n\n"); - des_modes(NSS_DES_EDE3, PR_TRUE, 24, tdea1_ecb_enc_key, - NULL, tdea1_ecb_enc_inp, 1); - } else if (strcmp(argv[1], "tdea_5_1_1_6_2") == 0) { - printf("Modes Test for the Encryption Process\n"); - printf("DATA FILE UTILIZED: datecbmontee2\n\n"); - des_modes(NSS_DES_EDE3, PR_TRUE, 24, tdea2_ecb_enc_key, - NULL, tdea2_ecb_enc_inp, 2); - } else if (strcmp(argv[1], "tdea_5_1_1_6_1") == 0) { - printf("Modes Test for the Encryption Process\n"); - printf("DATA FILE UTILIZED: datecbmontee3\n\n"); - des_modes(NSS_DES_EDE3, PR_TRUE, 24, tdea3_ecb_enc_key, - NULL, tdea3_ecb_enc_inp, 3); - /* decrypt */ - } else if (strcmp(argv[1], "tdea_5_1_2_1") == 0) { - printf("Variable Ciphertext Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - des_var_pt_kat(NSS_DES_EDE3, PR_FALSE, 24, key, NULL, NULL); - } else if (strcmp(argv[1], "tdea_5_1_2_2") == 0) { - printf("Inverse Permutation Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - des_inv_perm_kat(NSS_DES_EDE3, PR_FALSE, 24, key, NULL, NULL); - } else if (strcmp(argv[1], "tdea_5_1_2_3") == 0) { - printf("Variable Key Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - des_var_key_kat(NSS_DES_EDE3, PR_FALSE, 24, key, NULL, inp); - } else if (strcmp(argv[1], "tdea_5_1_2_4") == 0) { - printf("Permutation Operation Known Answer Test - Decryption\n\n"); - des_perm_op_kat(NSS_DES_EDE3, PR_FALSE, 24, NULL, NULL, inp); - } else if (strcmp(argv[1], "tdea_5_1_2_5") == 0) { - printf("Substitution Table Known Answer Test - Decryption\n\n"); - des_sub_tbl_kat(NSS_DES_EDE3, PR_FALSE, 24, NULL, NULL, NULL); - } else if (strcmp(argv[1], "tdea_5_1_2_6_3") == 0) { - printf("Modes Test for the Decryption Process\n"); - printf("DATA FILE UTILIZED: datecbmonted1\n\n"); - des_modes(NSS_DES_EDE3, PR_FALSE, 24, tdea1_ecb_dec_key, - NULL, tdea1_ecb_dec_inp, 1); - } else if (strcmp(argv[1], "tdea_5_1_2_6_2") == 0) { - printf("Modes Test for the Decryption Process\n"); - printf("DATA FILE UTILIZED: datecbmonted2\n\n"); - des_modes(NSS_DES_EDE3, PR_FALSE, 24, tdea2_ecb_dec_key, - NULL, tdea2_ecb_dec_inp, 2); - } else if (strcmp(argv[1], "tdea_5_1_2_6_1") == 0) { - printf("Modes Test for the Decryption Process\n"); - printf("DATA FILE UTILIZED: datecbmonted3\n\n"); - des_modes(NSS_DES_EDE3, PR_FALSE, 24, tdea3_ecb_dec_key, - NULL, tdea3_ecb_dec_inp, 3); - /**** CBC ****/ - /* encrypt */ - } else if (strcmp(argv[1], "tdea_5_2_1_1") == 0) { - printf("Variable Plaintext Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_var_pt_kat(NSS_DES_EDE3_CBC, PR_TRUE, 24, key, iv, NULL); - } else if (strcmp(argv[1], "tdea_5_2_1_2") == 0) { - printf("Inverse Plaintext Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_inv_perm_kat(NSS_DES_EDE3_CBC, PR_TRUE, 24, key, iv, NULL); - } else if (strcmp(argv[1], "tdea_5_2_1_3") == 0) { - printf("Variable Key Known Answer Test - Encryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_var_key_kat(NSS_DES_EDE3_CBC, PR_TRUE, 24, key, iv, inp); - } else if (strcmp(argv[1], "tdea_5_2_1_4") == 0) { - printf("Permutation Operation Known Answer Test - Encryption\n\n"); - memset(iv, 0, sizeof iv); - des_perm_op_kat(NSS_DES_EDE3_CBC, PR_TRUE, 24, NULL, iv, inp); - } else if (strcmp(argv[1], "tdea_5_2_1_5") == 0) { - memset(iv, 0, sizeof iv); - printf("Substitution Table Known Answer Test - Encryption\n\n"); - des_sub_tbl_kat(NSS_DES_EDE3_CBC, PR_TRUE, 24, NULL, iv, NULL); - } else if (strcmp(argv[1], "tdea_5_2_1_6_3") == 0) { - printf("Modes Test for the Encryption Process\n"); - printf("DATA FILE UTILIZED: datcbcmontee1\n\n"); - des_modes(NSS_DES_EDE3_CBC, PR_TRUE, 24, tdea1_cbc_enc_key, - tdea1_cbc_enc_iv, tdea1_cbc_enc_inp, 1); - } else if (strcmp(argv[1], "tdea_5_2_1_6_2") == 0) { - printf("Modes Test for the Encryption Process\n"); - printf("DATA FILE UTILIZED: datcbcmontee2\n\n"); - des_modes(NSS_DES_EDE3_CBC, PR_TRUE, 24, tdea2_cbc_enc_key, - tdea2_cbc_enc_iv, tdea2_cbc_enc_inp, 2); - } else if (strcmp(argv[1], "tdea_5_2_1_6_1") == 0) { - printf("Modes Test for the Encryption Process\n"); - printf("DATA FILE UTILIZED: datcbcmontee3\n\n"); - des_modes(NSS_DES_EDE3_CBC, PR_TRUE, 24, tdea3_cbc_enc_key, - tdea3_cbc_enc_iv, tdea3_cbc_enc_inp, 3); - /* decrypt */ - } else if (strcmp(argv[1], "tdea_5_2_2_1") == 0) { - printf("Variable Ciphertext Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_var_pt_kat(NSS_DES_EDE3_CBC, PR_FALSE, 24, key, iv, NULL); - } else if (strcmp(argv[1], "tdea_5_2_2_2") == 0) { - printf("Inverse Permutation Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_inv_perm_kat(NSS_DES_EDE3_CBC, PR_FALSE, 24, key, iv, NULL); - } else if (strcmp(argv[1], "tdea_5_2_2_3") == 0) { - printf("Variable Key Known Answer Test - Decryption\n\n"); - memset(key, 1, sizeof key); - memset(iv, 0, sizeof iv); - des_var_key_kat(NSS_DES_EDE3_CBC, PR_FALSE, 24, key, iv, inp); - } else if (strcmp(argv[1], "tdea_5_2_2_4") == 0) { - printf("Permutation Operation Known Answer Test - Decryption\n\n"); - memset(iv, 0, sizeof iv); - des_perm_op_kat(NSS_DES_EDE3_CBC, PR_FALSE, 24, NULL, iv, inp); - } else if (strcmp(argv[1], "tdea_5_2_2_5") == 0) { - printf("Substitution Table Known Answer Test - Decryption\n\n"); - memset(iv, 0, sizeof iv); - des_sub_tbl_kat(NSS_DES_EDE3_CBC, PR_FALSE, 24, NULL, iv, NULL); - } else if (strcmp(argv[1], "tdea_5_2_2_6_3") == 0) { - printf("Modes Test for the Decryption Process\n"); - printf("DATA FILE UTILIZED: datcbcmonted1\n\n"); - des_modes(NSS_DES_EDE3_CBC, PR_FALSE, 24, tdea1_cbc_dec_key, - tdea1_cbc_dec_iv, tdea1_cbc_dec_inp, 1); - } else if (strcmp(argv[1], "tdea_5_2_2_6_2") == 0) { - printf("Modes Test for the Decryption Process\n"); - printf("DATA FILE UTILIZED: datcbcmonted2\n\n"); - des_modes(NSS_DES_EDE3_CBC, PR_FALSE, 24, tdea2_cbc_dec_key, - tdea2_cbc_dec_iv, tdea2_cbc_dec_inp, 2); - } else if (strcmp(argv[1], "tdea_5_2_2_6_1") == 0) { - printf("Modes Test for the Decryption Process\n"); - printf("DATA FILE UTILIZED: datcbcmonted3\n\n"); - des_modes(NSS_DES_EDE3_CBC, PR_FALSE, 24, tdea3_cbc_dec_key, - tdea3_cbc_dec_iv, tdea3_cbc_dec_inp, 3); + if (strcmp(argv[1], "tdea") == 0) { + /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */ + if (strcmp(argv[2], "kat") == 0) { + /* Known Answer Test (KAT) */ + tdea_kat_mmt(argv[4]); + } else if (strcmp(argv[2], "mmt") == 0) { + /* Multi-block Message Test (MMT) */ + tdea_kat_mmt(argv[4]); + } else if (strcmp(argv[2], "mct") == 0) { + /* Monte Carlo Test (MCT) */ + if (strcmp(argv[3], "ecb") == 0) { + /* ECB mode */ + tdea_mct(NSS_DES_EDE3, argv[4]); + } else if (strcmp(argv[3], "cbc") == 0) { + /* CBC mode */ + tdea_mct(NSS_DES_EDE3_CBC, argv[4]); + } + } /*************/ /* AES */ /*************/ @@ -2632,20 +4513,82 @@ int main(int argc, char **argv) } } /*************/ - /* SHS */ + /* SHA */ + /*************/ + } else if (strcmp(argv[1], "sha") == 0) { + sha_test(argv[2]); + /*************/ + /* RSA */ /*************/ - } else if (strcmp(argv[1], "shs") == 0) { - shs_test(argv[2]); + } else if (strcmp(argv[1], "rsa") == 0) { + /* argv[2]=siggen|sigver */ + /* argv[3]=<test name>.req */ + if (strcmp(argv[2], "siggen") == 0) { + /* Signature Generation Test */ + rsa_siggen_test(argv[3]); + } else if (strcmp(argv[2], "sigver") == 0) { + /* Signature Verification Test */ + rsa_sigver_test(argv[3]); + } /*************/ - /* DSS */ + /* HMAC */ /*************/ - } else if (strcmp(argv[1], "dss") == 0) { - dss_test(argv[2], argv[3]); + } else if (strcmp(argv[1], "hmac") == 0) { + hmac_test(argv[2]); + /*************/ + /* DSA */ + /*************/ + } else if (strcmp(argv[1], "dsa") == 0) { + /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */ + /* argv[3]=<test name>.req */ + if (strcmp(argv[2], "keypair") == 0) { + /* Key Pair Generation Test */ + dsa_keypair_test(argv[3]); + } else if (strcmp(argv[2], "pqggen") == 0) { + /* Domain Parameter Generation Test */ + dsa_pqggen_test(argv[3]); + } else if (strcmp(argv[2], "pqgver") == 0) { + /* Domain Parameter Validation Test */ + dsa_pqgver_test(argv[3]); + } else if (strcmp(argv[2], "siggen") == 0) { + /* Signature Generation Test */ + dsa_siggen_test(argv[3]); + } else if (strcmp(argv[2], "sigver") == 0) { + /* Signature Verification Test */ + dsa_sigver_test(argv[3]); + } +#ifdef NSS_ENABLE_ECC + /*************/ + /* ECDSA */ + /*************/ + } else if (strcmp(argv[1], "ecdsa") == 0) { + /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */ + if ( strcmp(argv[2], "keypair") == 0) { + /* Key Pair Generation Test */ + ecdsa_keypair_test(argv[3]); + } else if (strcmp(argv[2], "pkv") == 0) { + /* Public Key Validation Test */ + ecdsa_pkv_test(argv[3]); + } else if (strcmp(argv[2], "siggen") == 0) { + /* Signature Generation Test */ + ecdsa_siggen_test(argv[3]); + } else if (strcmp(argv[2], "sigver") == 0) { + /* Signature Verification Test */ + ecdsa_sigver_test(argv[3]); + } +#endif /* NSS_ENABLE_ECC */ /*************/ /* RNG */ /*************/ } else if (strcmp(argv[1], "rng") == 0) { - do_random(); + /* argv[2]=vst|mct argv[3]=<test name>.req */ + if ( strcmp(argv[2], "vst") == 0) { + /* Variable Seed Test */ + rng_vst(argv[3]); + } else if (strcmp(argv[2], "mct") == 0) { + /* Monte Carlo Test */ + rng_mct(argv[3]); + } } return 0; } |