/** * PKCS #1 OAEP decoding */ static int OAEP_decode(unsigned char *message, unsigned int encoded_bytes, const unsigned char *encoded, unsigned int label_bytes, const unsigned char *label) { unsigned int i, message_bytes; unsigned char DB[RSA_MOD_BYTES - RSA_SHA_BYTES - 1 /* Add MGF1 buffer space */ + 4]; unsigned char seed[RSA_SHA_BYTES /* Add MGF1 buffer space */ + 4]; debugValue("OAEP decode: encoded message", encoded, encoded_bytes); // First byte of encoded message must be 0x00 if(encoded[0] != 0x00) { debugError("First byte of OAEP encoded message is not 0x00"); return RSA_ERROR_OAEP_DECODE; } // Extract maskedDB and maskedSeed debugValue("OAEP decode: maskedSeed", encoded + 1, RSA_SHA_BYTES); Copy(RSA_SHA_BYTES, DB, encoded + 1 + RSA_SHA_BYTES); debugValue("OAEP decode: maskedDB", encoded + 1 + RSA_SHA_BYTES, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); // Finding seed and DB MGF1(RSA_MOD_BYTES - RSA_SHA_BYTES - 1, DB, RSA_SHA_BYTES, seed); debugValue("OAEP decode: seedMask", seed, RSA_SHA_BYTES); XorAssign(RSA_SHA_BYTES, seed, encoded + 1); debugValue("OAEP decode: seed", seed, RSA_SHA_BYTES); MGF1(RSA_SHA_BYTES, seed, RSA_MOD_BYTES - RSA_SHA_BYTES - 1, DB); debugValue("OAEP decode: dbMask", DB, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); XorAssign(RSA_MOD_BYTES - RSA_SHA_BYTES - 1, DB, encoded + 1 + RSA_SHA_BYTES); debugValue("OAEP decode: DB", DB, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); // Compute the hash of l debugValue("OAEP decode: label", label, label_bytes); SHA(RSA_SHA_BYTES, seed, label_bytes, label); debugValue("OAEP decode: hash of label", seed, RSA_SHA_BYTES); // Check whether the first RSA_SHA_BYTES bytes of DB equal to lHash if (NotEqual(RSA_SHA_BYTES, seed, DB)) { debugError("First RSA_SHA_BYTES of DB do not match with hash of label"); return RSA_ERROR_OAEP_DECODE; } // Try to locate the message in DB i = RSA_SHA_BYTES; while ((DB[i] == 0x00) && (DB[i] != 0x01) && (i < (RSA_MOD_BYTES - RSA_SHA_BYTES - 1 - 1))) i++; if ((i == (RSA_MOD_BYTES - RSA_SHA_BYTES - 1 - 1)) || (DB[i] != 0x01)) { debugError("Failed to locate the message in DB"); return RSA_ERROR_OAEP_DECODE; } // Extract the message, starting after 0x01 byte to the end of DB message_bytes = RSA_MOD_BYTES - RSA_SHA_BYTES - 1 - 1 - (i + 1) + 1; CopyBytes(message_bytes, message, DB + i + 1); debugValue("OAEP decode: recovered message", message, message_bytes); return message_bytes; }
/** * PKCS #1 PSS verification */ static int PSS_verify(unsigned int message_bytes, const unsigned char *message, unsigned int encoded_bytes, const unsigned char *encoded) { unsigned char M[8 + RSA_SHA_BYTES + RSA_SALT_BYTES]; unsigned char DB[RSA_MOD_BYTES - RSA_SHA_BYTES - 1]; debugValue("PSS verify: message", message, message_bytes); if (encoded_bytes != RSA_MOD_BYTES) { return RSA_ERROR_PSS_INCONSISTENT; } debugValue("PSS verify: encoded message", encoded, encoded_bytes); // Verification if (encoded[RSA_MOD_BYTES - 1] != 0xbc) { return RSA_ERROR_PSS_INCONSISTENT; } // Extract maskedDB and H debugValue("PSS verify: maskedDB", encoded, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); Copy(RSA_SHA_BYTES, M + 8, encoded + RSA_MOD_BYTES - RSA_SHA_BYTES - 1); debugValue("PSS verify: H", encoded + RSA_MOD_BYTES - RSA_SHA_BYTES - 1, RSA_SHA_BYTES); // Compute DB MGF1(RSA_SHA_BYTES, M + 8, RSA_MOD_BYTES - RSA_SHA_BYTES - 1, DB); debugValue("PSS verify: dbMask", DB, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); XorAssign(RSA_MOD_BYTES - RSA_SHA_BYTES - 1, DB, encoded); debugValue("PSS verify: DB", DB, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); if (DB[RSA_MOD_BYTES - RSA_SALT_BYTES - RSA_SHA_BYTES - 2] != 0x01) { return RSA_ERROR_PSS_INCONSISTENT; } // Compute hash of m SHA(RSA_SHA_BYTES, M + 8, message_bytes, message); debugValue("PSS verify: hash of message", M + 8, RSA_SHA_BYTES); Copy(RSA_SALT_BYTES, M + 8 + RSA_SHA_BYTES, DB + RSA_MOD_BYTES - RSA_SALT_BYTES - RSA_SHA_BYTES - 1); debugValue("PSS verify: recovered message to be encoded", M, 8 + RSA_SHA_BYTES + RSA_SALT_BYTES); SHA(RSA_SHA_BYTES, DB, 8 + RSA_SHA_BYTES + RSA_SALT_BYTES, M); debugValue("PSS verify: hash of recovered message to be encoded", DB, RSA_SHA_BYTES); if (NotEqual(RSA_SHA_BYTES, encoded + RSA_MOD_BYTES - RSA_SHA_BYTES - 1, DB)) { debugWarning("PSS verify: verification failed"); return RSA_ERROR_PSS_INCONSISTENT; } debugMessage("PSS verify: verification succeeded"); return RSA_PSS_CONSISTENT; }
/** * PKCS #1 OAEP encoding */ static int OAEP_encode(unsigned char *encoded, unsigned int message_bytes, const unsigned char *message, unsigned int label_bytes, const unsigned char *label) { unsigned char DB[RSA_MOD_BYTES - RSA_SHA_BYTES - 1 /* Add MGF1 buffer space */ + 4]; unsigned char seed[RSA_SHA_BYTES /* Add MGF1 buffer space */ + 4]; // Construct DB debugValue("OAEP encode: label", label, label_bytes); SHA(RSA_SHA_BYTES, DB, label_bytes, label); debugValue("OAEP encode: hash of label", DB, RSA_SHA_BYTES); DB[RSA_MOD_BYTES - RSA_SHA_BYTES - message_bytes - 2] = 0x01; debugValue("OAEP encode: message", message, message_bytes); CopyBytes(message_bytes, DB + RSA_MOD_BYTES - RSA_SHA_BYTES - message_bytes - 1, message); debugValue("OAEP encode: DB", DB, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); // Make a random seed RandomBytes(seed, RSA_SHA_BYTES); debugValue("OAEP encode: seed", seed, RSA_SHA_BYTES); // Construct maskedDB and maskedSeed MGF1(RSA_SHA_BYTES, seed, RSA_MOD_BYTES - RSA_SHA_BYTES - 1, encoded + 1 + RSA_SHA_BYTES); debugValue("OAEP encode: dbMask", encoded + 1 + RSA_SHA_BYTES, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); XorAssign(RSA_MOD_BYTES - RSA_SHA_BYTES - 1, DB, encoded + 1 + RSA_SHA_BYTES); debugValue("OAEP encode: maskedDB", DB, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); MGF1(RSA_MOD_BYTES - RSA_SHA_BYTES - 1, DB, RSA_SHA_BYTES, encoded + 1); debugValue("OAEP encode: seedMask", encoded + 1, RSA_SHA_BYTES); XorAssign(RSA_SHA_BYTES, seed, encoded + 1); debugValue("OAEP encode: maskedSeed", encoded + 1, RSA_SHA_BYTES); Copy(RSA_SHA_BYTES, encoded + 1, seed); Copy(RSA_MOD_BYTES - RSA_SHA_BYTES - 1, encoded + 1 + RSA_SHA_BYTES, DB); debugValue("OAEP encode: encoded message", encoded, RSA_MOD_BYTES); return RSA_MOD_BYTES; }
/** * PKCS #1 PSS encoding */ static int PSS_encode(unsigned char *encoded, unsigned int message_bytes, const unsigned char *message) { unsigned char M[8 + RSA_SHA_BYTES + RSA_SALT_BYTES]; unsigned char DB[RSA_MOD_BYTES - RSA_SHA_BYTES - 1]; // Compute the hash of m debugValue("PSS encode: message", message, message_bytes); SHA(RSA_SHA_BYTES, M + 8, message_bytes, message); debugValue("PSS encode: hashed message", M + 8, RSA_SHA_BYTES); // Generate the salt and construct M RandomBytes(M + 8 + RSA_SHA_BYTES, RSA_SALT_BYTES); debugValue("PSS encode: salt", M + 8 + RSA_SHA_BYTES, RSA_SALT_BYTES); debugValue("PSS encode: message to be encoded", M, 8 + RSA_SHA_BYTES + RSA_SALT_BYTES); // Construct DB DB[RSA_MOD_BYTES - RSA_SALT_BYTES - RSA_SHA_BYTES - 2] = 0x01; Copy(RSA_SALT_BYTES, DB + RSA_MOD_BYTES - RSA_SALT_BYTES - RSA_SHA_BYTES - 1, M + 8 + RSA_SHA_BYTES); debugValue("PSS encode: DB", DB, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); // Compute maskedDB SHA(RSA_SHA_BYTES, encoded + RSA_MOD_BYTES - RSA_SHA_BYTES - 1, 8 + RSA_SHA_BYTES + RSA_SALT_BYTES, M); debugValue("PSS encode: hash of message to be encoded", encoded + RSA_MOD_BYTES - RSA_SHA_BYTES - 1, RSA_SHA_BYTES); Copy(RSA_SHA_BYTES, M, encoded + RSA_MOD_BYTES - RSA_SHA_BYTES - 1); MGF1(RSA_SHA_BYTES, M, RSA_MOD_BYTES - RSA_SHA_BYTES - 1, encoded); debugValue("PSS encode: dbMask", encoded, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); XorAssign(RSA_MOD_BYTES - RSA_SHA_BYTES - 1, DB, encoded); debugValue("PSS encode: maskedDB", encoded, RSA_MOD_BYTES - RSA_SHA_BYTES - 1); // Construct the encoded message Copy(RSA_MOD_BYTES - RSA_SHA_BYTES - 1, encoded, DB); encoded[RSA_MOD_BYTES - 1] = 0xbc; debugValue("PSS encode: encoded message", encoded, RSA_MOD_BYTES); return RSA_MOD_BYTES; }
/* PSEC-KEM key encapsulation mechanism Return: TRUE if succeed; otherwise FALSE */ u8 PSEC_KEM_KEM( PSEC_KEM_PUB_KEY *publicKey, /* PSEC_KEM public key */ PSEC_KEM_KEY_ENCAPSULATION *keyEncapsulation, /* returned keyEncapsulation */ PSEC_KEM_KEY_MATERIAL *keyMaterial, /* returned key material */ EC_PARAM *E, PSEC_KEM_EC_ENCODING_FORMAT format ) { mpz_t s, u, res, v; u8 *s_raw, *u_raw, *t_raw, *mgf_arg_1, *mgf_arg_2, *res_raw, *v_raw, *PEH_raw; u8 *EG_raw; s32 i; u32 hoLen, uoLen, EGoLen, PEHoLen, qoLen; EC_POINT h_tilde, g_tilde; mpz_init(s); mpz_init(u); mpz_init(res); mpz_init(v); hoLen = (publicKey->hLen) >> 3; uoLen = (u32)ceil(E->pLen/8.0) + 16; keyMaterial->KoLen = (publicKey->outputKeyLen) >> 3; qoLen = (u32)ceil(E->qLen/8.0); if (format == COMPRESSED) { EGoLen = 1 + qoLen; PEHoLen = 1 + qoLen; } else { EGoLen = 1 + 2*qoLen; PEHoLen = 1 + 2*qoLen; } if ((publicKey->pk).inf_id == EC_O) PEHoLen = 1; if ((E->P).inf_id == EC_O) EGoLen = 1; #ifdef DEBUG printf("hoLen = %u\n", hoLen); printf("uoLen = %u\n", uoLen); printf("keyMaterial->KoLen = %u\n", keyMaterial->KoLen); printf("EGoLen = %u\n", EGoLen); printf("PEHoLen = %u\n", PEHoLen); #endif EC_initPoint ( &h_tilde ); EC_initPoint ( &g_tilde); s_raw = (BYTE *) malloc (hoLen); u_raw = (BYTE *) malloc (uoLen); t_raw = (BYTE *) malloc (uoLen + keyMaterial->KoLen); mgf_arg_1 = (u8 *) malloc (4 + hoLen); mgf_arg_2 = (u8 *) malloc (4 + EGoLen + PEHoLen); res_raw = (u8 *) malloc (hoLen); v_raw = (u8 *) malloc (hoLen); PEH_raw = (u8 *) malloc (PEHoLen); EG_raw = (u8 *) malloc (EGoLen); /* generate s */ GenerateBytes(s_raw, hoLen, global_prng); BYTE2WORD (s, s_raw, hoLen); #ifdef DEBUG printf("s = 0x%s\n", mpz_get_str(NULL, 16, s)); printf("\n"); fflush(stdout); #endif /* compute t = MGF1(0 || s) */ U32TO8_BIG(mgf_arg_1, 0L); memcpy(mgf_arg_1+4, s_raw, hoLen); MGF1( t_raw, 8 * (uoLen + keyMaterial->KoLen), mgf_arg_1, 4 + hoLen); #ifdef DEBUG printf("t = "); printAsHex(t_raw, uoLen+keyMaterial->KoLen); printf("\n"); fflush(stdout); #endif /* parse t as t = u || K */ memcpy( u_raw, t_raw, uoLen ); BYTE2WORD( u, u_raw, uoLen ); memcpy( keyMaterial->K_raw, t_raw+uoLen, keyMaterial->KoLen ); #ifdef DEBUG printf("u = 0x%s\n", mpz_get_str(NULL, 16, u)); printf("keyMaterial = "); printAsHex(keyMaterial->K_raw, keyMaterial->KoLen); printf("\n"); fflush(stdout); #endif /* compute h_tilde = u * publicKey->pk */ EC_Mult( &h_tilde, u, &(publicKey->pk), E ); ec2os (PEH_raw, &h_tilde, E, format); #ifdef DEBUG printf("h_tilde.x = 0x%s\n", mpz_get_str(NULL, 16, h_tilde.x)); printf("h_tilde.y = 0x%s\n", mpz_get_str(NULL, 16, h_tilde.y)); printf("PEH = "); printAsHex(PEH_raw, PEHoLen); printf("\n"); fflush(stdout); #endif /* compute g_tilde = u * E->P */ EC_Mult( &g_tilde, u, &(E->P), E ); #ifdef DEBUG printf("g_tilde.x = 0x%s\n", mpz_get_str(NULL, 16, g_tilde.x)); printf("g_tilde.y = 0x%s\n", mpz_get_str(NULL, 16, g_tilde.y)); printf("g_tilde.inf_id = %u\n", g_tilde.inf_id); #endif /* convert g_tilde's EC point to an octet string according to P1363 E.2.3.2 */ ec2os( EG_raw, &g_tilde, E, format); #ifdef DEBUG printf("EG = "); printAsHex(EG_raw, EGoLen); printf("\n"); fflush(stdout); #endif /* compute res = MGF1( 1 || EG || PEH ) */ U32TO8_BIG ( mgf_arg_2, 1L ); memcpy( mgf_arg_2 + 4, EG_raw, EGoLen ); memcpy( mgf_arg_2 + 4 + EGoLen, PEH_raw, PEHoLen ); MGF1( res_raw, publicKey->hLen, mgf_arg_2, 4 + EGoLen + PEHoLen); BYTE2WORD( res, res_raw, hoLen); #ifdef DEBUG printf("res = 0x%s\n", mpz_get_str(NULL, 16, res)); printf("\n"); fflush(stdout); #endif /* compute v = s \xor res */ mpz_xor(v, s, res); WORD2BYTE(v_raw, v, hoLen); #ifdef DEBUG printf("v = 0x%s\n", mpz_get_str(NULL, 16, v)); printf("\n"); fflush(stdout); #endif /* output C0 = EG || v */ memcpy( keyEncapsulation->C0, EG_raw, EGoLen); memcpy( keyEncapsulation->C0 + EGoLen, v_raw, hoLen); #ifdef DEBUG printf("C0 = "); printAsHex(keyEncapsulation->C0, keyEncapsulation->C0oLen); printf("\n"); fflush(stdout); #endif /* clean up */ mpz_clear(s); mpz_clear(u); mpz_clear(res); mpz_clear(v); memset(s_raw, 0, hoLen); memset(u_raw, 0, uoLen); memset(t_raw, 0, uoLen + keyMaterial->KoLen); memset(mgf_arg_1, 0, 4+hoLen); memset(mgf_arg_2, 0, 4 + EGoLen + PEHoLen); memset(res_raw, 0, hoLen); memset(v_raw, 0, hoLen); memset(PEH_raw, 0, PEHoLen); memset(EG_raw, 0, EGoLen); free(s_raw); free(u_raw); free(t_raw); free(mgf_arg_1); free(mgf_arg_2); free(res_raw); free(v_raw); free(PEH_raw); free(EG_raw); EC_clearPoint ( &h_tilde ); EC_clearPoint ( &g_tilde ); return TRUE; }