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  */