github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-amcl/amcl/GCM.go (about) 1 /* 2 Licensed to the Apache Software Foundation (ASF) under one 3 or more contributor license agreements. See the NOTICE file 4 distributed with this work for additional information 5 regarding copyright ownership. The ASF licenses this file 6 to you under the Apache License, Version 2.0 (the 7 "License"); you may not use this file except in compliance 8 with the License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, 13 software distributed under the License is distributed on an 14 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 KIND, either express or implied. See the License for the 16 specific language governing permissions and limitations 17 under the License. 18 */ 19 20 /* 21 * Implementation of the AES-GCM Encryption/Authentication 22 * 23 * Some restrictions.. 24 * 1. Only for use with AES 25 * 2. Returned tag is always 128-bits. Truncate at your own risk. 26 * 3. The order of function calls must follow some rules 27 * 28 * Typical sequence of calls.. 29 * 1. call GCM_init 30 * 2. call GCM_add_header any number of times, as long as length of header is multiple of 16 bytes (block size) 31 * 3. call GCM_add_header one last time with any length of header 32 * 4. call GCM_add_cipher any number of times, as long as length of cipher/plaintext is multiple of 16 bytes 33 * 5. call GCM_add_cipher one last time with any length of cipher/plaintext 34 * 6. call GCM_finish to extract the tag. 35 * 36 * See http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf 37 */ 38 39 40 package amcl 41 42 import 43 ( 44 // "fmt" 45 "strconv" 46 ) 47 48 const gcm_NB int=4 49 const GCM_ACCEPTING_HEADER int=0 50 const GCM_ACCEPTING_CIPHER int=1 51 const GCM_NOT_ACCEPTING_MORE int=2 52 const GCM_FINISHED int=3 53 const GCM_ENCRYPTING int=0 54 const GCM_DECRYPTING int=1 55 56 57 type GCM struct { 58 table [128][4]uint32 /* 2k bytes */ 59 stateX [16]byte 60 Y_0 [16]byte 61 counter int 62 lenA [2]uint32 63 lenC [2]uint32 64 status int 65 a *AES 66 } 67 68 func gcm_pack(b [4]byte) uint32 { /* pack bytes into a 32-bit Word */ 69 return ((uint32(b[0])&0xff)<<24)|((uint32(b[1])&0xff)<<16)|((uint32(b[2])&0xff)<<8)|(uint32(b[3])&0xff) 70 } 71 72 func gcm_unpack(a uint32) [4]byte { /* unpack bytes from a word */ 73 var b=[4]byte{byte((a>>24)&0xff),byte((a>>16)&0xff),byte((a>>8)&0xff),byte(a&0xff)} 74 return b; 75 } 76 77 func (G *GCM) precompute(H []byte) { 78 var b [4]byte 79 j:=0 80 for i:=0;i<gcm_NB;i++ { 81 b[0]=H[j]; b[1]=H[j+1]; b[2]=H[j+2]; b[3]=H[j+3] 82 G.table[0][i]=gcm_pack(b); 83 j+=4 84 } 85 for i:=1;i<128;i++ { 86 c:=uint32(0) 87 for j:=0;j<gcm_NB;j++ {G.table[i][j]=c|(G.table[i-1][j])>>1; c=G.table[i-1][j]<<31;} 88 if c != 0 {G.table[i][0]^=0xE1000000} /* irreducible polynomial */ 89 } 90 } 91 92 func (G *GCM) gf2mul() { /* gf2m mul - Z=H*X mod 2^128 */ 93 var P [4]uint32 94 95 for i:=0;i<4;i++ {P[i]=0} 96 j:=uint(8); m:=0 97 for i:=0;i<128;i++ { 98 j-- 99 c:=uint32((G.stateX[m]>>j)&1); c=^c+1 100 for k:=0;k<gcm_NB;k++ {P[k]^=(G.table[i][k]&c)} 101 if j==0 { 102 j=8; m++; 103 if m==16 {break} 104 } 105 } 106 j=0 107 for i:=0;i<gcm_NB;i++ { 108 b:=gcm_unpack(P[i]) 109 G.stateX[j]=b[0]; G.stateX[j+1]=b[1]; G.stateX[j+2]=b[2]; G.stateX[j+3]=b[3]; 110 j+=4 111 } 112 } 113 114 func (G *GCM) wrap() { /* Finish off GHASH */ 115 var F [4]uint32 116 var L [16]byte 117 118 /* convert lengths from bytes to bits */ 119 F[0]=(G.lenA[0]<<3)|(G.lenA[1]&0xE0000000)>>29 120 F[1]=G.lenA[1]<<3 121 F[2]=(G.lenC[0]<<3)|(G.lenC[1]&0xE0000000)>>29 122 F[3]=G.lenC[1]<<3 123 j:=0 124 for i:=0;i<gcm_NB;i++ { 125 b:=gcm_unpack(F[i]); 126 L[j]=b[0]; L[j+1]=b[1]; L[j+2]=b[2]; L[j+3]=b[3] 127 j+=4 128 } 129 for i:=0;i<16;i++ {G.stateX[i]^=L[i]} 130 G.gf2mul() 131 } 132 133 func (G *GCM) ghash(plain []byte,len int) bool { 134 if G.status==GCM_ACCEPTING_HEADER {G.status=GCM_ACCEPTING_CIPHER} 135 if G.status != GCM_ACCEPTING_CIPHER {return false} 136 137 j:=0 138 for (j<len) { 139 for i:=0;i<16 && j<len;i++ { 140 G.stateX[i]^=plain[j]; j++ 141 G.lenC[1]++; if G.lenC[1]==0 {G.lenC[0]++} 142 } 143 G.gf2mul(); 144 } 145 if len%16 != 0 {G.status=GCM_NOT_ACCEPTING_MORE} 146 return true; 147 } 148 149 /* Initialize GCM mode */ 150 func (G *GCM) Init(nk int,key []byte,niv int,iv []byte) { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */ 151 var H [16]byte 152 153 for i:=0;i<16;i++ {H[i]=0; G.stateX[i]=0} 154 155 G.a=new(AES) 156 157 G.a.Init(AES_ECB,nk,key,iv) 158 G.a.ecb_encrypt(H[:]) /* E(K,0) */ 159 G.precompute(H[:]) 160 161 G.lenA[0]=0;G.lenC[0]=0;G.lenA[1]=0;G.lenC[1]=0 162 if niv==12 { 163 for i:=0;i<12;i++ {G.a.f[i]=iv[i]} 164 b:=gcm_unpack(uint32(1)) 165 G.a.f[12]=b[0]; G.a.f[13]=b[1]; G.a.f[14]=b[2]; G.a.f[15]=b[3]; /* initialise IV */ 166 for i:=0;i<16;i++ {G.Y_0[i]=G.a.f[i]} 167 } else { 168 G.status=GCM_ACCEPTING_CIPHER; 169 G.ghash(iv,niv) /* GHASH(H,0,IV) */ 170 G.wrap() 171 for i:=0;i<16;i++ {G.a.f[i]=G.stateX[i];G.Y_0[i]=G.a.f[i];G.stateX[i]=0} 172 G.lenA[0]=0;G.lenC[0]=0;G.lenA[1]=0;G.lenC[1]=0 173 } 174 G.status=GCM_ACCEPTING_HEADER 175 } 176 177 /* Add Header data - included but not encrypted */ 178 func (G *GCM) Add_header(header []byte,len int) bool { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */ 179 if G.status != GCM_ACCEPTING_HEADER {return false} 180 181 j:=0 182 for j<len { 183 for i:=0;i<16 && j<len;i++ { 184 G.stateX[i]^=header[j]; j++ 185 G.lenA[1]++; if G.lenA[1]==0 {G.lenA[0]++} 186 } 187 G.gf2mul(); 188 } 189 if len%16 != 0 {G.status=GCM_ACCEPTING_CIPHER} 190 191 return true; 192 } 193 194 /* Add Plaintext - included and encrypted */ 195 func (G *GCM) Add_plain(plain []byte,len int) []byte { 196 var B [16]byte 197 var b [4]byte 198 199 cipher:=make([]byte,len) 200 var counter uint32=0 201 if G.status == GCM_ACCEPTING_HEADER {G.status=GCM_ACCEPTING_CIPHER} 202 if G.status != GCM_ACCEPTING_CIPHER {return nil} 203 204 j:=0 205 for j<len { 206 207 b[0]=G.a.f[12]; b[1]=G.a.f[13]; b[2]=G.a.f[14]; b[3]=G.a.f[15]; 208 counter=gcm_pack(b) 209 counter++ 210 b=gcm_unpack(counter) 211 G.a.f[12]=b[0]; G.a.f[13]=b[1]; G.a.f[14]=b[2]; G.a.f[15]=b[3] /* increment counter */ 212 for i:=0;i<16;i++ {B[i]=G.a.f[i]} 213 G.a.ecb_encrypt(B[:]); /* encrypt it */ 214 215 for i:=0;i<16 && j<len;i++ { 216 cipher[j]=(plain[j]^B[i]) 217 G.stateX[i]^=cipher[j]; j++ 218 G.lenC[1]++; if G.lenC[1]==0 {G.lenC[0]++} 219 } 220 G.gf2mul() 221 } 222 if len%16 != 0 {G.status=GCM_NOT_ACCEPTING_MORE} 223 return cipher 224 } 225 226 /* Add Ciphertext - decrypts to plaintext */ 227 func (G *GCM) Add_cipher(cipher []byte,len int) []byte { 228 var B [16]byte 229 var b [4]byte 230 231 plain:=make([]byte,len) 232 var counter uint32=0 233 234 if G.status==GCM_ACCEPTING_HEADER {G.status=GCM_ACCEPTING_CIPHER} 235 if G.status != GCM_ACCEPTING_CIPHER {return nil} 236 237 j:=0 238 for j<len { 239 b[0]=G.a.f[12]; b[1]=G.a.f[13]; b[2]=G.a.f[14]; b[3]=G.a.f[15] 240 counter=gcm_pack(b); 241 counter++ 242 b=gcm_unpack(counter) 243 G.a.f[12]=b[0]; G.a.f[13]=b[1]; G.a.f[14]=b[2]; G.a.f[15]=b[3]; /* increment counter */ 244 for i:=0;i<16;i++ {B[i]=G.a.f[i]} 245 G.a.ecb_encrypt(B[:]) /* encrypt it */ 246 for i:=0;i<16 && j<len;i++ { 247 oc:=cipher[j]; 248 plain[j]=(cipher[j]^B[i]) 249 G.stateX[i]^=oc; j++ 250 G.lenC[1]++; if G.lenC[1]==0 {G.lenC[0]++} 251 } 252 G.gf2mul() 253 } 254 if len%16 != 0 {G.status=GCM_NOT_ACCEPTING_MORE} 255 return plain 256 } 257 258 /* Finish and extract Tag */ 259 func (G *GCM) Finish(extract bool) [16]byte { /* Finish off GHASH and extract tag (MAC) */ 260 var tag [16]byte 261 262 G.wrap() 263 /* extract tag */ 264 if extract { 265 G.a.ecb_encrypt(G.Y_0[:]); /* E(K,Y0) */ 266 for i:=0;i<16;i++ {G.Y_0[i]^=G.stateX[i]} 267 for i:=0;i<16;i++ {tag[i]=G.Y_0[i];G.Y_0[i]=0;G.stateX[i]=0} 268 } 269 G.status=GCM_FINISHED 270 G.a.End() 271 return tag 272 } 273 274 func hex2bytes(s string) []byte { 275 lgh:=len(s) 276 data:=make([]byte,lgh/2) 277 278 for i:=0;i<lgh;i+=2 { 279 a,_ := strconv.ParseInt(s[i:i+2],16,32) 280 data[i/2]=byte(a) 281 } 282 return data 283 } 284 285 /* 286 func main() { 287 288 KT:="feffe9928665731c6d6a8f9467308308" 289 MT:="d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39" 290 HT:="feedfacedeadbeeffeedfacedeadbeefabaddad2" 291 292 NT:="9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b"; 293 // Tag should be 619cc5aefffe0bfa462af43c1699d050 294 295 g:=new(GCM) 296 297 M:=hex2bytes(MT) 298 H:=hex2bytes(HT) 299 N:=hex2bytes(NT) 300 K:=hex2bytes(KT) 301 302 lenM:=len(M) 303 lenH:=len(H) 304 lenK:=len(K) 305 lenIV:=len(N) 306 307 fmt.Printf("Plaintext=\n"); 308 for i:=0;i<lenM;i++ {fmt.Printf("%02x",M[i])} 309 fmt.Printf("\n") 310 311 g.Init(lenK,K,lenIV,N) 312 g.Add_header(H,lenH) 313 C:=g.Add_plain(M,lenM) 314 T:=g.Finish(true) 315 316 fmt.Printf("Ciphertext=\n") 317 for i:=0;i<lenM;i++ {fmt.Printf("%02x",C[i])} 318 fmt.Printf("\n") 319 320 fmt.Printf("Tag=\n") 321 for i:=0;i<16;i++ {fmt.Printf("%02x",T[i])} 322 fmt.Printf("\n") 323 324 g.Init(lenK,K,lenIV,N) 325 g.Add_header(H,lenH) 326 P:=g.Add_cipher(C,lenM) 327 T=g.Finish(true) 328 329 fmt.Printf("Plaintext=\n"); 330 for i:=0;i<lenM;i++ {fmt.Printf("%02x",P[i])} 331 fmt.Printf("\n") 332 333 fmt.Printf("Tag=\n"); 334 for i:=0;i<16;i++ {fmt.Printf("%02x",T[i])} 335 fmt.Printf("\n") 336 } 337 */