OLD | NEW |
(Empty) | |
| 1 // Copyright 2011 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. |
| 4 |
| 5 package packet |
| 6 |
| 7 import ( |
| 8 "bytes" |
| 9 "code.google.com/p/go.crypto/openpgp/errors" |
| 10 "code.google.com/p/go.crypto/openpgp/s2k" |
| 11 "crypto/cipher" |
| 12 "io" |
| 13 "strconv" |
| 14 ) |
| 15 |
| 16 // This is the largest session key that we'll support. Since no 512-bit cipher |
| 17 // has even been seriously used, this is comfortably large. |
| 18 const maxSessionKeySizeInBytes = 64 |
| 19 |
| 20 // SymmetricKeyEncrypted represents a passphrase protected session key. See RFC |
| 21 // 4880, section 5.3. |
| 22 type SymmetricKeyEncrypted struct { |
| 23 CipherFunc CipherFunction |
| 24 Encrypted bool |
| 25 Key []byte // Empty unless Encrypted is false. |
| 26 s2k func(out, in []byte) |
| 27 encryptedKey []byte |
| 28 } |
| 29 |
| 30 const symmetricKeyEncryptedVersion = 4 |
| 31 |
| 32 func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err error) { |
| 33 // RFC 4880, section 5.3. |
| 34 var buf [2]byte |
| 35 _, err = readFull(r, buf[:]) |
| 36 if err != nil { |
| 37 return |
| 38 } |
| 39 if buf[0] != symmetricKeyEncryptedVersion { |
| 40 return errors.UnsupportedError("SymmetricKeyEncrypted version") |
| 41 } |
| 42 ske.CipherFunc = CipherFunction(buf[1]) |
| 43 |
| 44 if ske.CipherFunc.KeySize() == 0 { |
| 45 return errors.UnsupportedError("unknown cipher: " + strconv.Itoa
(int(buf[1]))) |
| 46 } |
| 47 |
| 48 ske.s2k, err = s2k.Parse(r) |
| 49 if err != nil { |
| 50 return |
| 51 } |
| 52 |
| 53 encryptedKey := make([]byte, maxSessionKeySizeInBytes) |
| 54 // The session key may follow. We just have to try and read to find |
| 55 // out. If it exists then we limit it to maxSessionKeySizeInBytes. |
| 56 n, err := readFull(r, encryptedKey) |
| 57 if err != nil && err != io.ErrUnexpectedEOF { |
| 58 return |
| 59 } |
| 60 err = nil |
| 61 if n != 0 { |
| 62 if n == maxSessionKeySizeInBytes { |
| 63 return errors.UnsupportedError("oversized encrypted sess
ion key") |
| 64 } |
| 65 ske.encryptedKey = encryptedKey[:n] |
| 66 } |
| 67 |
| 68 ske.Encrypted = true |
| 69 |
| 70 return |
| 71 } |
| 72 |
| 73 // Decrypt attempts to decrypt an encrypted session key. If it returns nil, |
| 74 // ske.Key will contain the session key. |
| 75 func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) error { |
| 76 if !ske.Encrypted { |
| 77 return nil |
| 78 } |
| 79 |
| 80 key := make([]byte, ske.CipherFunc.KeySize()) |
| 81 ske.s2k(key, passphrase) |
| 82 |
| 83 if len(ske.encryptedKey) == 0 { |
| 84 ske.Key = key |
| 85 } else { |
| 86 // the IV is all zeros |
| 87 iv := make([]byte, ske.CipherFunc.blockSize()) |
| 88 c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) |
| 89 c.XORKeyStream(ske.encryptedKey, ske.encryptedKey) |
| 90 ske.CipherFunc = CipherFunction(ske.encryptedKey[0]) |
| 91 if ske.CipherFunc.blockSize() == 0 { |
| 92 return errors.UnsupportedError("unknown cipher: " + strc
onv.Itoa(int(ske.CipherFunc))) |
| 93 } |
| 94 ske.CipherFunc = CipherFunction(ske.encryptedKey[0]) |
| 95 ske.Key = ske.encryptedKey[1:] |
| 96 if len(ske.Key)%ske.CipherFunc.blockSize() != 0 { |
| 97 ske.Key = nil |
| 98 return errors.StructuralError("length of decrypted key n
ot a multiple of block size") |
| 99 } |
| 100 } |
| 101 |
| 102 ske.Encrypted = false |
| 103 return nil |
| 104 } |
| 105 |
| 106 // SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The |
| 107 // packet contains a random session key, encrypted by a key derived from the |
| 108 // given passphrase. The session key is returned and must be passed to |
| 109 // SerializeSymmetricallyEncrypted. |
| 110 func SerializeSymmetricKeyEncrypted(w io.Writer, rand io.Reader, passphrase []by
te, cipherFunc CipherFunction) (key []byte, err error) { |
| 111 keySize := cipherFunc.KeySize() |
| 112 if keySize == 0 { |
| 113 return nil, errors.UnsupportedError("unknown cipher: " + strconv
.Itoa(int(cipherFunc))) |
| 114 } |
| 115 |
| 116 s2kBuf := new(bytes.Buffer) |
| 117 keyEncryptingKey := make([]byte, keySize) |
| 118 // s2k.Serialize salts and stretches the passphrase, and writes the |
| 119 // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. |
| 120 err = s2k.Serialize(s2kBuf, keyEncryptingKey, rand, passphrase) |
| 121 if err != nil { |
| 122 return |
| 123 } |
| 124 s2kBytes := s2kBuf.Bytes() |
| 125 |
| 126 packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + k
eySize |
| 127 err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) |
| 128 if err != nil { |
| 129 return |
| 130 } |
| 131 |
| 132 var buf [2]byte |
| 133 buf[0] = symmetricKeyEncryptedVersion |
| 134 buf[1] = byte(cipherFunc) |
| 135 _, err = w.Write(buf[:]) |
| 136 if err != nil { |
| 137 return |
| 138 } |
| 139 _, err = w.Write(s2kBytes) |
| 140 if err != nil { |
| 141 return |
| 142 } |
| 143 |
| 144 sessionKey := make([]byte, keySize) |
| 145 _, err = io.ReadFull(rand, sessionKey) |
| 146 if err != nil { |
| 147 return |
| 148 } |
| 149 iv := make([]byte, cipherFunc.blockSize()) |
| 150 c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) |
| 151 encryptedCipherAndKey := make([]byte, keySize+1) |
| 152 c.XORKeyStream(encryptedCipherAndKey, buf[1:]) |
| 153 c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) |
| 154 _, err = w.Write(encryptedCipherAndKey) |
| 155 if err != nil { |
| 156 return |
| 157 } |
| 158 |
| 159 key = sessionKey |
| 160 return |
| 161 } |
OLD | NEW |