Botan
1.11.15
|
00001 /* 00002 * PSSR 00003 * (C) 1999-2007 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/pad_utils.h> 00009 #include <botan/pssr.h> 00010 #include <botan/mgf1.h> 00011 #include <botan/internal/bit_ops.h> 00012 00013 namespace Botan { 00014 00015 PSSR* PSSR::make(const Spec& request) 00016 { 00017 if(request.arg(1, "MGF1") != "MGF1") 00018 return nullptr; 00019 00020 auto hash = make_a<HashFunction>(request.arg(0)); 00021 00022 if(!hash) 00023 return nullptr; 00024 00025 const size_t salt_size = request.arg_as_integer(2, hash->output_length()); 00026 00027 return new PSSR(hash, salt_size); 00028 } 00029 00030 BOTAN_REGISTER_NAMED_T(EMSA, "PSSR", PSSR, PSSR::make); 00031 00032 /* 00033 * PSSR Update Operation 00034 */ 00035 void PSSR::update(const byte input[], size_t length) 00036 { 00037 hash->update(input, length); 00038 } 00039 00040 /* 00041 * Return the raw (unencoded) data 00042 */ 00043 secure_vector<byte> PSSR::raw_data() 00044 { 00045 return hash->final(); 00046 } 00047 00048 /* 00049 * PSSR Encode Operation 00050 */ 00051 secure_vector<byte> PSSR::encoding_of(const secure_vector<byte>& msg, 00052 size_t output_bits, 00053 RandomNumberGenerator& rng) 00054 { 00055 const size_t HASH_SIZE = hash->output_length(); 00056 00057 if(msg.size() != HASH_SIZE) 00058 throw Encoding_Error("PSSR::encoding_of: Bad input length"); 00059 if(output_bits < 8*HASH_SIZE + 8*SALT_SIZE + 9) 00060 throw Encoding_Error("PSSR::encoding_of: Output length is too small"); 00061 00062 const size_t output_length = (output_bits + 7) / 8; 00063 00064 secure_vector<byte> salt = rng.random_vec(SALT_SIZE); 00065 00066 for(size_t j = 0; j != 8; ++j) 00067 hash->update(0); 00068 hash->update(msg); 00069 hash->update(salt); 00070 secure_vector<byte> H = hash->final(); 00071 00072 secure_vector<byte> EM(output_length); 00073 00074 EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01; 00075 buffer_insert(EM, output_length - 1 - HASH_SIZE - SALT_SIZE, salt); 00076 mgf1_mask(*hash, &H[0], HASH_SIZE, &EM[0], output_length - HASH_SIZE - 1); 00077 EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits); 00078 buffer_insert(EM, output_length - 1 - HASH_SIZE, H); 00079 EM[output_length-1] = 0xBC; 00080 00081 return EM; 00082 } 00083 00084 /* 00085 * PSSR Decode/Verify Operation 00086 */ 00087 bool PSSR::verify(const secure_vector<byte>& const_coded, 00088 const secure_vector<byte>& raw, size_t key_bits) 00089 { 00090 const size_t HASH_SIZE = hash->output_length(); 00091 const size_t KEY_BYTES = (key_bits + 7) / 8; 00092 00093 if(key_bits < 8*HASH_SIZE + 9) 00094 return false; 00095 00096 if(raw.size() != HASH_SIZE) 00097 return false; 00098 00099 if(const_coded.size() > KEY_BYTES || const_coded.size() <= 1) 00100 return false; 00101 00102 if(const_coded[const_coded.size()-1] != 0xBC) 00103 return false; 00104 00105 secure_vector<byte> coded = const_coded; 00106 if(coded.size() < KEY_BYTES) 00107 { 00108 secure_vector<byte> temp(KEY_BYTES); 00109 buffer_insert(temp, KEY_BYTES - coded.size(), coded); 00110 coded = temp; 00111 } 00112 00113 const size_t TOP_BITS = 8 * ((key_bits + 7) / 8) - key_bits; 00114 if(TOP_BITS > 8 - high_bit(coded[0])) 00115 return false; 00116 00117 byte* DB = &coded[0]; 00118 const size_t DB_size = coded.size() - HASH_SIZE - 1; 00119 00120 const byte* H = &coded[DB_size]; 00121 const size_t H_size = HASH_SIZE; 00122 00123 mgf1_mask(*hash, &H[0], H_size, &DB[0], DB_size); 00124 DB[0] &= 0xFF >> TOP_BITS; 00125 00126 size_t salt_offset = 0; 00127 for(size_t j = 0; j != DB_size; ++j) 00128 { 00129 if(DB[j] == 0x01) 00130 { salt_offset = j + 1; break; } 00131 if(DB[j]) 00132 return false; 00133 } 00134 if(salt_offset == 0) 00135 return false; 00136 00137 for(size_t j = 0; j != 8; ++j) 00138 hash->update(0); 00139 hash->update(raw); 00140 hash->update(&DB[salt_offset], DB_size - salt_offset); 00141 secure_vector<byte> H2 = hash->final(); 00142 00143 return same_mem(&H[0], &H2[0], HASH_SIZE); 00144 } 00145 00146 PSSR::PSSR(HashFunction* h) : 00147 SALT_SIZE(h->output_length()), hash(h) 00148 { 00149 } 00150 00151 PSSR::PSSR(HashFunction* h, size_t salt_size) : 00152 SALT_SIZE(salt_size), hash(h) 00153 { 00154 } 00155 00156 }