github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/asserts/crypto.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2015-2016 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package asserts 21 22 import ( 23 "bytes" 24 "crypto" 25 "crypto/rand" 26 "crypto/rsa" 27 _ "crypto/sha256" // be explicit about supporting SHA256 28 _ "crypto/sha512" // be explicit about needing SHA512 29 "encoding/base64" 30 "fmt" 31 "io" 32 "time" 33 34 "golang.org/x/crypto/openpgp/packet" 35 "golang.org/x/crypto/sha3" 36 ) 37 38 const ( 39 maxEncodeLineLength = 76 40 v1 = 0x1 41 ) 42 43 var ( 44 v1Header = []byte{v1} 45 v1FixedTimestamp = time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC) 46 ) 47 48 func encodeV1(data []byte) []byte { 49 buf := new(bytes.Buffer) 50 buf.Grow(base64.StdEncoding.EncodedLen(len(data) + 1)) 51 enc := base64.NewEncoder(base64.StdEncoding, buf) 52 enc.Write(v1Header) 53 enc.Write(data) 54 enc.Close() 55 flat := buf.Bytes() 56 flatSize := len(flat) 57 58 buf = new(bytes.Buffer) 59 buf.Grow(flatSize + flatSize/maxEncodeLineLength + 1) 60 off := 0 61 for { 62 endOff := off + maxEncodeLineLength 63 if endOff > flatSize { 64 endOff = flatSize 65 } 66 buf.Write(flat[off:endOff]) 67 off = endOff 68 if off >= flatSize { 69 break 70 } 71 buf.WriteByte('\n') 72 } 73 74 return buf.Bytes() 75 } 76 77 type keyEncoder interface { 78 keyEncode(w io.Writer) error 79 } 80 81 func encodeKey(key keyEncoder, kind string) ([]byte, error) { 82 buf := new(bytes.Buffer) 83 err := key.keyEncode(buf) 84 if err != nil { 85 return nil, fmt.Errorf("cannot encode %s: %v", kind, err) 86 } 87 return encodeV1(buf.Bytes()), nil 88 } 89 90 type openpgpSigner interface { 91 sign(content []byte) (*packet.Signature, error) 92 } 93 94 func signContent(content []byte, privateKey PrivateKey) ([]byte, error) { 95 signer, ok := privateKey.(openpgpSigner) 96 if !ok { 97 panic(fmt.Errorf("not an internally supported PrivateKey: %T", privateKey)) 98 } 99 100 sig, err := signer.sign(content) 101 if err != nil { 102 return nil, err 103 } 104 105 buf := new(bytes.Buffer) 106 err = sig.Serialize(buf) 107 if err != nil { 108 return nil, err 109 } 110 111 return encodeV1(buf.Bytes()), nil 112 } 113 114 func decodeV1(b []byte, kind string) (packet.Packet, error) { 115 if len(b) == 0 { 116 return nil, fmt.Errorf("cannot decode %s: no data", kind) 117 } 118 buf := make([]byte, base64.StdEncoding.DecodedLen(len(b))) 119 n, err := base64.StdEncoding.Decode(buf, b) 120 if err != nil { 121 return nil, fmt.Errorf("cannot decode %s: %v", kind, err) 122 } 123 if n == 0 { 124 return nil, fmt.Errorf("cannot decode %s: base64 without data", kind) 125 } 126 buf = buf[:n] 127 if buf[0] != v1 { 128 return nil, fmt.Errorf("unsupported %s format version: %d", kind, buf[0]) 129 } 130 rd := bytes.NewReader(buf[1:]) 131 pkt, err := packet.Read(rd) 132 if err != nil { 133 return nil, fmt.Errorf("cannot decode %s: %v", kind, err) 134 } 135 if rd.Len() != 0 { 136 return nil, fmt.Errorf("%s has spurious trailing data", kind) 137 } 138 return pkt, nil 139 } 140 141 func decodeSignature(signature []byte) (*packet.Signature, error) { 142 pkt, err := decodeV1(signature, "signature") 143 if err != nil { 144 return nil, err 145 } 146 sig, ok := pkt.(*packet.Signature) 147 if !ok { 148 return nil, fmt.Errorf("expected signature, got instead: %T", pkt) 149 } 150 return sig, nil 151 } 152 153 // PublicKey is the public part of a cryptographic private/public key pair. 154 type PublicKey interface { 155 // ID returns the id of the key used for lookup. 156 ID() string 157 158 // verify verifies signature is valid for content using the key. 159 verify(content []byte, sig *packet.Signature) error 160 161 keyEncoder 162 } 163 164 type openpgpPubKey struct { 165 pubKey *packet.PublicKey 166 sha3_384 string 167 } 168 169 func (opgPubKey *openpgpPubKey) ID() string { 170 return opgPubKey.sha3_384 171 } 172 173 func (opgPubKey *openpgpPubKey) verify(content []byte, sig *packet.Signature) error { 174 h := sig.Hash.New() 175 h.Write(content) 176 return opgPubKey.pubKey.VerifySignature(h, sig) 177 } 178 179 func (opgPubKey openpgpPubKey) keyEncode(w io.Writer) error { 180 return opgPubKey.pubKey.Serialize(w) 181 } 182 183 func newOpenPGPPubKey(intPubKey *packet.PublicKey) *openpgpPubKey { 184 h := sha3.New384() 185 h.Write(v1Header) 186 err := intPubKey.Serialize(h) 187 if err != nil { 188 panic("internal error: cannot compute public key sha3-384") 189 } 190 sha3_384, err := EncodeDigest(crypto.SHA3_384, h.Sum(nil)) 191 if err != nil { 192 panic("internal error: cannot compute public key sha3-384") 193 } 194 return &openpgpPubKey{pubKey: intPubKey, sha3_384: sha3_384} 195 } 196 197 // RSAPublicKey returns a database useable public key out of rsa.PublicKey. 198 func RSAPublicKey(pubKey *rsa.PublicKey) PublicKey { 199 intPubKey := packet.NewRSAPublicKey(v1FixedTimestamp, pubKey) 200 return newOpenPGPPubKey(intPubKey) 201 } 202 203 // DecodePublicKey deserializes a public key. 204 func DecodePublicKey(pubKey []byte) (PublicKey, error) { 205 pkt, err := decodeV1(pubKey, "public key") 206 if err != nil { 207 return nil, err 208 } 209 pubk, ok := pkt.(*packet.PublicKey) 210 if !ok { 211 return nil, fmt.Errorf("expected public key, got instead: %T", pkt) 212 } 213 rsaPubKey, ok := pubk.PublicKey.(*rsa.PublicKey) 214 if !ok { 215 return nil, fmt.Errorf("expected RSA public key, got instead: %T", pubk.PublicKey) 216 } 217 return RSAPublicKey(rsaPubKey), nil 218 } 219 220 // EncodePublicKey serializes a public key, typically for embedding in an assertion. 221 func EncodePublicKey(pubKey PublicKey) ([]byte, error) { 222 return encodeKey(pubKey, "public key") 223 } 224 225 // PrivateKey is a cryptographic private/public key pair. 226 type PrivateKey interface { 227 // PublicKey returns the public part of the pair. 228 PublicKey() PublicKey 229 230 keyEncoder 231 } 232 233 type openpgpPrivateKey struct { 234 privk *packet.PrivateKey 235 } 236 237 func (opgPrivK openpgpPrivateKey) PublicKey() PublicKey { 238 return newOpenPGPPubKey(&opgPrivK.privk.PublicKey) 239 } 240 241 func (opgPrivK openpgpPrivateKey) keyEncode(w io.Writer) error { 242 return opgPrivK.privk.Serialize(w) 243 } 244 245 var openpgpConfig = &packet.Config{ 246 DefaultHash: crypto.SHA512, 247 } 248 249 func (opgPrivK openpgpPrivateKey) sign(content []byte) (*packet.Signature, error) { 250 privk := opgPrivK.privk 251 sig := new(packet.Signature) 252 sig.PubKeyAlgo = privk.PubKeyAlgo 253 sig.Hash = openpgpConfig.Hash() 254 sig.CreationTime = time.Now() 255 256 h := openpgpConfig.Hash().New() 257 h.Write(content) 258 259 err := sig.Sign(h, privk, openpgpConfig) 260 if err != nil { 261 return nil, err 262 } 263 264 return sig, nil 265 } 266 267 func decodePrivateKey(privKey []byte) (PrivateKey, error) { 268 pkt, err := decodeV1(privKey, "private key") 269 if err != nil { 270 return nil, err 271 } 272 privk, ok := pkt.(*packet.PrivateKey) 273 if !ok { 274 return nil, fmt.Errorf("expected private key, got instead: %T", pkt) 275 } 276 if _, ok := privk.PrivateKey.(*rsa.PrivateKey); !ok { 277 return nil, fmt.Errorf("expected RSA private key, got instead: %T", privk.PrivateKey) 278 } 279 return openpgpPrivateKey{privk}, nil 280 } 281 282 // RSAPrivateKey returns a PrivateKey for database use out of a rsa.PrivateKey. 283 func RSAPrivateKey(privk *rsa.PrivateKey) PrivateKey { 284 intPrivk := packet.NewRSAPrivateKey(v1FixedTimestamp, privk) 285 return openpgpPrivateKey{intPrivk} 286 } 287 288 // GenerateKey generates a private/public key pair. 289 func GenerateKey() (PrivateKey, error) { 290 priv, err := rsa.GenerateKey(rand.Reader, 4096) 291 if err != nil { 292 return nil, err 293 } 294 return RSAPrivateKey(priv), nil 295 } 296 297 func encodePrivateKey(privKey PrivateKey) ([]byte, error) { 298 return encodeKey(privKey, "private key") 299 } 300 301 // externally held key pairs 302 303 type extPGPPrivateKey struct { 304 pubKey PublicKey 305 from string 306 pgpFingerprint string 307 bitLen int 308 doSign func(content []byte) ([]byte, error) 309 } 310 311 func newExtPGPPrivateKey(exportedPubKeyStream io.Reader, from string, sign func(content []byte) ([]byte, error)) (*extPGPPrivateKey, error) { 312 var pubKey *packet.PublicKey 313 314 rd := packet.NewReader(exportedPubKeyStream) 315 for { 316 pkt, err := rd.Next() 317 if err == io.EOF { 318 break 319 } 320 if err != nil { 321 return nil, fmt.Errorf("cannot read exported public key: %v", err) 322 } 323 cand, ok := pkt.(*packet.PublicKey) 324 if ok { 325 if cand.IsSubkey { 326 continue 327 } 328 if pubKey != nil { 329 return nil, fmt.Errorf("cannot select exported public key, found many") 330 } 331 pubKey = cand 332 } 333 } 334 335 if pubKey == nil { 336 return nil, fmt.Errorf("cannot read exported public key, found none (broken export)") 337 338 } 339 340 rsaPubKey, ok := pubKey.PublicKey.(*rsa.PublicKey) 341 if !ok { 342 return nil, fmt.Errorf("not a RSA key") 343 } 344 345 return &extPGPPrivateKey{ 346 pubKey: RSAPublicKey(rsaPubKey), 347 from: from, 348 pgpFingerprint: fmt.Sprintf("%X", pubKey.Fingerprint), 349 bitLen: rsaPubKey.N.BitLen(), 350 doSign: sign, 351 }, nil 352 } 353 354 func (expk *extPGPPrivateKey) fingerprint() string { 355 return expk.pgpFingerprint 356 } 357 358 func (expk *extPGPPrivateKey) PublicKey() PublicKey { 359 return expk.pubKey 360 } 361 362 func (expk *extPGPPrivateKey) keyEncode(w io.Writer) error { 363 return fmt.Errorf("cannot access external private key to encode it") 364 } 365 366 func (expk *extPGPPrivateKey) sign(content []byte) (*packet.Signature, error) { 367 if expk.bitLen < 4096 { 368 return nil, fmt.Errorf("signing needs at least a 4096 bits key, got %d", expk.bitLen) 369 } 370 371 out, err := expk.doSign(content) 372 if err != nil { 373 return nil, err 374 } 375 376 badSig := fmt.Sprintf("bad %s produced signature: ", expk.from) 377 378 sigpkt, err := packet.Read(bytes.NewBuffer(out)) 379 if err != nil { 380 return nil, fmt.Errorf(badSig+"%v", err) 381 } 382 383 sig, ok := sigpkt.(*packet.Signature) 384 if !ok { 385 return nil, fmt.Errorf(badSig+"got %T", sigpkt) 386 } 387 388 if sig.Hash != crypto.SHA512 { 389 return nil, fmt.Errorf(badSig + "expected SHA512 digest") 390 } 391 392 err = expk.pubKey.verify(content, sig) 393 if err != nil { 394 return nil, fmt.Errorf(badSig+"it does not verify: %v", err) 395 } 396 397 return sig, nil 398 }