github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/caam/ecdsa.go (about) 1 // NXP Cryptographic Acceleration and Assurance Module (CAAM) driver 2 // https://github.com/usbarmory/tamago 3 // 4 // Copyright (c) WithSecure Corporation 5 // https://foundry.withsecure.com 6 // 7 // Use of this source code is governed by the license 8 // that can be found in the LICENSE file. 9 10 package caam 11 12 import ( 13 "bytes" 14 "crypto/ecdsa" 15 "encoding/binary" 16 "errors" 17 "fmt" 18 "math/big" 19 20 "github.com/usbarmory/tamago/bits" 21 "github.com/usbarmory/tamago/dma" 22 ) 23 24 // p451, Table 8-112, IMX7DSSRM 25 const ( 26 DSA_SIG_PDB_PD = 22 27 DSA_SIG_PDB_ECDSEL = 7 28 ) 29 30 // p443, Table 8-101, IMX7DSSRM 31 const ( 32 // Table 8-101 33 ECDSEL_P256 = 0x02 34 ECDSEL_P256K1 = 0x20 35 ) 36 37 // SignPDB represents an ECDSA sign protocol data block (PDB). 38 type SignPDB struct { 39 // size of the group 40 n int 41 // elliptic curve domain selection 42 ecdsel int 43 // private key 44 s uint 45 // message hash 46 f uint 47 // signature buffer 48 c uint 49 // signature buffer (2nd part, n length) 50 d uint 51 52 // DMA buffer 53 sig []byte 54 } 55 56 // Init initializes a PDB for ECDSA signing. 57 func (pdb *SignPDB) Init(priv *ecdsa.PrivateKey) (err error) { 58 name := priv.PublicKey.Curve.Params().Name 59 60 switch name { 61 case "P-256": 62 pdb.n = 32 63 pdb.ecdsel = ECDSEL_P256 64 case "P-256k1": 65 pdb.n = 32 66 pdb.ecdsel = ECDSEL_P256K1 67 default: 68 return fmt.Errorf("unsupported curve %s", name) 69 } 70 71 pdb.n = priv.PublicKey.Curve.Params().BitSize / 8 72 73 pdb.s = dma.Alloc(make([]byte, pdb.n), 4) 74 dma.Write(pdb.s, 0, priv.D.Bytes()) 75 76 pdb.f, _ = dma.Reserve(pdb.n, 4) 77 78 pdb.c, pdb.sig = dma.Reserve(pdb.n*2, 4) 79 pdb.d = pdb.c + uint(pdb.n) 80 81 return 82 } 83 84 func (pdb *SignPDB) Hash(hash []byte) { 85 dma.Write(pdb.f, 0, hash[0:pdb.n]) 86 } 87 88 // Bytes converts the PDB to byte array format. 89 func (pdb *SignPDB) Bytes() []byte { 90 var word0 uint32 91 92 // p451, Table 8-112, IMX7DSSRM 93 94 bits.Set(&word0, DSA_SIG_PDB_PD) 95 bits.SetN(&word0, DSA_SIG_PDB_ECDSEL, 0x7f, uint32(pdb.ecdsel)) 96 97 buf := new(bytes.Buffer) 98 binary.Write(buf, binary.LittleEndian, uint32(word0)) 99 binary.Write(buf, binary.LittleEndian, uint32(pdb.s)) 100 binary.Write(buf, binary.LittleEndian, uint32(pdb.f)) 101 binary.Write(buf, binary.LittleEndian, uint32(pdb.c)) 102 binary.Write(buf, binary.LittleEndian, uint32(pdb.d)) 103 104 return buf.Bytes() 105 } 106 107 // Free frees the memory allocated by the PDB. 108 func (pdb *SignPDB) Free() { 109 dma.Release(pdb.c) 110 dma.Release(pdb.f) 111 dma.Free(pdb.s) 112 } 113 114 // Sign signs a hash (which should be the result of hashing a larger message) 115 // using the private key, priv. If the hash is longer than the bit-length of 116 // the private key's curve order, the hash will be truncated to that length. It 117 // returns the signature as a pair of integers. 118 // 119 // A previously initialized sign protocol data block (see SignPDB.Init()) may 120 // be passed to cache private key initialization, in this case priv is ignored. 121 func (hw *CAAM) Sign(priv *ecdsa.PrivateKey, hash []byte, pdb *SignPDB) (r, s *big.Int, err error) { 122 if pdb == nil { 123 pdb = &SignPDB{} 124 defer pdb.Free() 125 126 if err = pdb.Init(priv); err != nil { 127 return 128 } 129 } else if pdb.n == 0 { 130 return nil, nil, errors.New("pdb is not initialized") 131 } 132 133 pdb.Hash(hash) 134 jd := pdb.Bytes() 135 136 var info uint32 137 bits.Set(&info, PROTINFO_ECC) 138 bits.SetTo(&info, PROTINFO_SIGN_NO_TEQ, hw.DisableTimingEqualization) 139 140 op := Operation{} 141 op.SetDefaults() 142 op.OpType(OPTYPE_PROT_UNI) 143 op.Protocol(PROTID_ECDSA_SIGN, info) 144 145 hdr := &Header{} 146 hdr.SetDefaults() 147 hdr.StartIndex(1 + len(jd)/4) 148 149 jd = append(jd, op.Bytes()...) 150 hdr.Length(1 + len(jd)/4) 151 152 if err = hw.job(hdr, jd); err != nil { 153 return 154 } 155 156 r = &big.Int{} 157 r.SetBytes(pdb.sig[0:pdb.n]) 158 159 s = &big.Int{} 160 s.SetBytes(pdb.sig[pdb.n:]) 161 162 return 163 }