github.com/cloudflare/circl@v1.5.0/blindsign/blindrsa/internal/common/pss.go (about) 1 // Copyright (c) 2009 The Go Authors. All rights reserved. 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google Inc. nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 package common 30 31 // Copyright 2013 The Go Authors. All rights reserved. 32 // Use of this source code is governed by a BSD-style 33 // license that can be found in the LICENSE file. 34 35 // This file implements the RSASSA-PSS signature scheme according to RFC 8017. 36 37 import ( 38 "bytes" 39 "crypto/rsa" 40 "errors" 41 "hash" 42 ) 43 44 // Per RFC 8017, Section 9.1 45 // 46 // EM = MGF1 xor DB || H( 8*0x00 || mHash || salt ) || 0xbc 47 // 48 // where 49 // 50 // DB = PS || 0x01 || salt 51 // 52 // and PS can be empty so 53 // 54 // emLen = dbLen + hLen + 1 = psLen + sLen + hLen + 2 55 // 56 57 func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) { 58 // See RFC 8017, Section 9.1.1. 59 60 hLen := hash.Size() 61 sLen := len(salt) 62 emLen := (emBits + 7) / 8 63 64 // 1. If the length of M is greater than the input limitation for the 65 // hash function (2^61 - 1 octets for SHA-1), output "message too 66 // long" and stop. 67 // 68 // 2. Let mHash = Hash(M), an octet string of length hLen. 69 70 if len(mHash) != hLen { 71 return nil, errors.New("crypto/rsa: input must be hashed with given hash") 72 } 73 74 // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. 75 76 if emLen < hLen+sLen+2 { 77 return nil, errors.New("crypto/rsa: key size too small for PSS signature") 78 } 79 80 em := make([]byte, emLen) 81 psLen := emLen - sLen - hLen - 2 82 db := em[:psLen+1+sLen] 83 h := em[psLen+1+sLen : emLen-1] 84 85 // 4. Generate a random octet string salt of length sLen; if sLen = 0, 86 // then salt is the empty string. 87 // 88 // 5. Let 89 // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt; 90 // 91 // M' is an octet string of length 8 + hLen + sLen with eight 92 // initial zero octets. 93 // 94 // 6. Let H = Hash(M'), an octet string of length hLen. 95 96 var prefix [8]byte 97 98 hash.Write(prefix[:]) 99 hash.Write(mHash) 100 hash.Write(salt) 101 102 h = hash.Sum(h[:0]) 103 hash.Reset() 104 105 // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2 106 // zero octets. The length of PS may be 0. 107 // 108 // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length 109 // emLen - hLen - 1. 110 111 db[psLen] = 0x01 112 copy(db[psLen+1:], salt) 113 114 // 9. Let dbMask = MGF(H, emLen - hLen - 1). 115 // 116 // 10. Let maskedDB = DB \xor dbMask. 117 118 mgf1XOR(db, hash, h) 119 120 // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in 121 // maskedDB to zero. 122 123 db[0] &= 0xff >> (8*emLen - emBits) 124 125 // 12. Let EM = maskedDB || H || 0xbc. 126 em[emLen-1] = 0xbc 127 128 // 13. Output EM. 129 return em, nil 130 } 131 132 func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { 133 // See RFC 8017, Section 9.1.2. 134 135 hLen := hash.Size() 136 if sLen == rsa.PSSSaltLengthEqualsHash { 137 sLen = hLen 138 } 139 emLen := (emBits + 7) / 8 140 if emLen != len(em) { 141 return errors.New("rsa: internal error: inconsistent length") 142 } 143 144 // 1. If the length of M is greater than the input limitation for the 145 // hash function (2^61 - 1 octets for SHA-1), output "inconsistent" 146 // and stop. 147 // 148 // 2. Let mHash = Hash(M), an octet string of length hLen. 149 if hLen != len(mHash) { 150 return rsa.ErrVerification 151 } 152 153 // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop. 154 if emLen < hLen+sLen+2 { 155 return rsa.ErrVerification 156 } 157 158 // 4. If the rightmost octet of EM does not have hexadecimal value 159 // 0xbc, output "inconsistent" and stop. 160 if em[emLen-1] != 0xbc { 161 return rsa.ErrVerification 162 } 163 164 // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and 165 // let H be the next hLen octets. 166 db := em[:emLen-hLen-1] 167 h := em[emLen-hLen-1 : emLen-1] 168 169 // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in 170 // maskedDB are not all equal to zero, output "inconsistent" and 171 // stop. 172 var bitMask byte = 0xff >> (8*emLen - emBits) 173 if em[0] & ^bitMask != 0 { 174 return rsa.ErrVerification 175 } 176 177 // 7. Let dbMask = MGF(H, emLen - hLen - 1). 178 // 179 // 8. Let DB = maskedDB \xor dbMask. 180 mgf1XOR(db, hash, h) 181 182 // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB 183 // to zero. 184 db[0] &= bitMask 185 186 // If we don't know the salt length, look for the 0x01 delimiter. 187 if sLen == rsa.PSSSaltLengthAuto { 188 psLen := bytes.IndexByte(db, 0x01) 189 if psLen < 0 { 190 return rsa.ErrVerification 191 } 192 sLen = len(db) - psLen - 1 193 } 194 195 // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero 196 // or if the octet at position emLen - hLen - sLen - 1 (the leftmost 197 // position is "position 1") does not have hexadecimal value 0x01, 198 // output "inconsistent" and stop. 199 psLen := emLen - hLen - sLen - 2 200 for _, e := range db[:psLen] { 201 if e != 0x00 { 202 return rsa.ErrVerification 203 } 204 } 205 if db[psLen] != 0x01 { 206 return rsa.ErrVerification 207 } 208 209 // 11. Let salt be the last sLen octets of DB. 210 salt := db[len(db)-sLen:] 211 212 // 12. Let 213 // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ; 214 // M' is an octet string of length 8 + hLen + sLen with eight 215 // initial zero octets. 216 // 217 // 13. Let H' = Hash(M'), an octet string of length hLen. 218 var prefix [8]byte 219 hash.Write(prefix[:]) 220 hash.Write(mHash) 221 hash.Write(salt) 222 223 h0 := hash.Sum(nil) 224 225 // 14. If H = H', output "consistent." Otherwise, output "inconsistent." 226 if !bytes.Equal(h0, h) { // TODO: constant time? 227 return rsa.ErrVerification 228 } 229 return nil 230 }