Add rsa_parse_block function to RSA mechanisms. The rsa_parse_block function parses an encryption block according to PKCS #1: RSA Encryption, Version 1.5.
Signed-off-by: Ramon de Carvalho Valle <[email protected]> --- usr/lib/pkcs11/common/mech_rsa.c | 201 ++++++++++++++++++++++++++++++++------ 1 files changed, 172 insertions(+), 29 deletions(-) diff --git a/usr/lib/pkcs11/common/mech_rsa.c b/usr/lib/pkcs11/common/mech_rsa.c index 87bfa1c..9c07dd5 100755 --- a/usr/lib/pkcs11/common/mech_rsa.c +++ b/usr/lib/pkcs11/common/mech_rsa.c @@ -400,6 +400,151 @@ rsa_format_block( CK_BYTE * in_data, } +/* + * Parse an encryption block according to PKCS #1: RSA Encryption, Version + * 1.5. + */ + +CK_RV +rsa_parse_block( CK_BYTE * in_data, + CK_ULONG in_data_len, + CK_BYTE * out_data, + CK_ULONG * out_data_len, + CK_ULONG type ) +{ + CK_ULONG i; + CK_RV rc; + + if (!in_data || !out_data || !out_data_len) { + st_err_log(4, __FILE__, __LINE__, __FUNCTION__); + rc = CKR_FUNCTION_FAILED; + return rc; + } + + if (in_data_len <= 11) { + st_err_log(4, __FILE__, __LINE__, __FUNCTION__); + rc = CKR_FUNCTION_FAILED; + return rc; + } + + /* + * Check for the leading 00 octet. + */ + if (in_data[0] != (CK_BYTE)0) { + st_err_log(14, __FILE__, __LINE__); + rc = CKR_ENCRYPTED_DATA_INVALID; + return rc; + } + + /* + * Check the block type. + */ + if (in_data[1] != (CK_BYTE)type) { + st_err_log(14, __FILE__, __LINE__); + rc = CKR_ENCRYPTED_DATA_INVALID; + return rc; + } + + /* + * The block type shall be a single octet indicating the structure of the + * encryption block. It shall have value 00, 01, or 02. For a private-key + * operation, the block type shall be 00 or 01. For a public-key + * operation, it shall be 02. + * + * For block type 00, the octets shall have value 00; for block type 01, + * they shall have value FF; and for block type 02, they shall be + * pseudorandomly generated and nonzero. + * + * For block type 00, the data must begin with a nonzero octet or have + * known length so that the encryption block can be parsed unambiguously. + * For block types 01 and 02, the encryption block can be parsed + * unambiguously since the padding string contains no octets with value 00 + * and the padding string is separated from the data by an octet with + * value 00. + */ + switch (type) { + /* + * For block type 00, the octets shall have value 00. + * EB = 00 || 00 || 00 * i || D + * Where D must begin with a nonzero octet. + */ + case 0: + for (i = 2; i < (in_data_len - 2); i++) { + if (in_data[i] != (CK_BYTE)0) + break; + } + break; + + /* + * For block type 01, they shall have value FF. + * EB = 00 || 01 || FF * i || 00 || D + */ + case 1: + for (i = 2; i < (in_data_len - 2); i++) { + if (in_data[i] != (CK_BYTE)0xff) { + if (in_data[i] == (CK_BYTE)0) { + i++; + break; + } + + st_err_log(14, __FILE__, __LINE__); + rc = CKR_ENCRYPTED_DATA_INVALID; + return rc; + } + } + break; + + /* + * For block type 02, they shall be pseudorandomly generated and + * nonzero. + * EB = 00 || 02 || ?? * i || 00 || D + * Where ?? is nonzero. + */ + case 2: + for (i = 2; i < (in_data_len - 2); i++) { + if (in_data[i] == (CK_BYTE)0) { + i++; + break; + } + } + break; + + default: + st_err_log(14, __FILE__, __LINE__); + rc = CKR_ENCRYPTED_DATA_INVALID; + return rc; + } + + /* + * For block types 01 and 02, the padding string is at least eight octets + * long, which is a security condition for public-key operations that + * prevents an attacker from recoving data by trying all possible + * encryption blocks. + */ + if ((type == 1 || type == 2) && ((i - 3) < 8)) { + st_err_log(112, __FILE__, __LINE__); + rc = CKR_ENCRYPTED_DATA_LEN_RANGE; + return rc; + } + + if (in_data_len <= i) { + st_err_log(112, __FILE__, __LINE__); + rc = CKR_ENCRYPTED_DATA_LEN_RANGE; + return rc; + } + + if (*out_data_len < (in_data_len - i)) { + st_err_log(68, __FILE__, __LINE__); + rc = CKR_BUFFER_TOO_SMALL; + return rc; + } + + memcpy(out_data, &in_data[i], in_data_len - i); + *out_data_len = in_data_len - i; + + rc = CKR_OK; + return rc; +} // // @@ -505,43 +650,41 @@ rsa_pkcs_decrypt( SESSION *sess, return CKR_OK; } - rc = ckm_rsa_decrypt( in_data, modulus_bytes, out, key_obj ); - if (rc == CKR_OK) { - CK_ULONG len; - - // strip off the PKCS block formatting data - // - // 00 | BT | PADDING | 00 | DATA - // - for (i=2; i < in_data_len; i++) { - if (out[i] == 0x0) { - i++; // point i at the first data byte - break; - } - } - - if (i == in_data_len){ - st_err_log(14, __FILE__, __LINE__); - return CKR_ENCRYPTED_DATA_INVALID; - } - len = in_data_len - i; + if (*out_data_len < (modulus_bytes - 11)) { + *out_data_len = modulus_bytes - 11; + st_err_log(68, __FILE__, __LINE__); + return CKR_BUFFER_TOO_SMALL; + } - if (len > *out_data_len) { - *out_data_len = len; - st_err_log(111, __FILE__, __LINE__); - return CKR_BUFFER_TOO_SMALL; + rc = ckm_rsa_decrypt( in_data, modulus_bytes, out, key_obj ); + if (rc != CKR_OK) { + if (rc == CKR_DATA_LEN_RANGE) { + st_err_log(112, __FILE__, __LINE__); + return CKR_ENCRYPTED_DATA_LEN_RANGE; } - memcpy( out_data, &out[i], len ); - *out_data_len = len; + st_err_log(133, __FILE__, __LINE__); + return rc; } - else + + rc = rsa_parse_block(out, modulus_bytes, out_data, out_data_len, PKCS_BT_2); + if (rc != CKR_OK) { + /* + * FIXME: rsa_parse_block() should have it's own error message. + */ st_err_log(133, __FILE__, __LINE__); + return rc; + } - if (rc == CKR_DATA_LEN_RANGE){ - st_err_log(109, __FILE__, __LINE__); + /* + * For PKCS #1 v1.5 padding, out_data_len must be less than + * modulus_bytes - 11. + */ + if (*out_data_len > (modulus_bytes - 11)) { + st_err_log(112, __FILE__, __LINE__); return CKR_ENCRYPTED_DATA_LEN_RANGE; } + return rc; } -- 1.7.0.4 ------------------------------------------------------------------------------ ThinkGeek and WIRED's GeekDad team up for the Ultimate GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the lucky parental unit. See the prize list and enter to win: http://p.sf.net/sfu/thinkgeek-promo _______________________________________________ Opencryptoki-tech mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/opencryptoki-tech
