├── go.mod ├── go.sum ├── crypto ├── aeswrap │ ├── aeswrap_test.go │ └── aeswrap.go └── gcm │ ├── LICENSE │ ├── xor.go │ └── gcm.go ├── LICENSE ├── encoding └── asn1 │ ├── LICENSE │ ├── marshal_test.go │ ├── common.go │ ├── marshal.go │ ├── asn1.go │ └── asn1_test.go ├── README.md ├── kvarchive └── keyed.go ├── keybag └── keybag.go ├── cmd └── irestore │ └── irestore.go └── backup └── backup.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/dunhamsteve/ios 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/dunhamsteve/plist v0.0.0-20211213035615-a528b51ff82f 7 | github.com/mattn/go-sqlite3 v1.14.15 8 | golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2 9 | ) 10 | 11 | require ( 12 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect 13 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/dunhamsteve/plist v0.0.0-20211213035615-a528b51ff82f h1:isN+gnW3pKSwhwGiENPfVy960FJ3uOI2K+x4X3r57AE= 2 | github.com/dunhamsteve/plist v0.0.0-20211213035615-a528b51ff82f/go.mod h1:wYdaZYuFSWCziwZl3+0BNSnBCw1FKv4/V2JtV+RA6Xc= 3 | github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= 4 | github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= 5 | golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2 h1:x8vtB3zMecnlqZIwJNUUpwYKYSqCz5jXbiyv0ZJJZeI= 6 | golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 7 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 8 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= 9 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 10 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= 11 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 12 | -------------------------------------------------------------------------------- /crypto/aeswrap/aeswrap_test.go: -------------------------------------------------------------------------------- 1 | package aeswrap 2 | 3 | import ( 4 | "encoding/hex" 5 | "testing" 6 | "bytes" 7 | ) 8 | 9 | func TestWrap(t *testing.T) { 10 | // A single test vector from the RFC. 11 | kek,_ := hex.DecodeString("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F") 12 | key,_ := hex.DecodeString("00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F") 13 | ctext,_ := hex.DecodeString("28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21") 14 | 15 | tmp := Wrap(kek,key) 16 | t.Logf("HAVE %x WANT %x",tmp,ctext) 17 | if !bytes.Equal(tmp,ctext) { 18 | t.Error("wrap failed") 19 | } 20 | } 21 | 22 | 23 | func TestUnwrap(t *testing.T) { 24 | // A single test vector from the RFC. 25 | kek,_ := hex.DecodeString("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F") 26 | key,_ := hex.DecodeString("00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F") 27 | ctext,_ := hex.DecodeString("28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21") 28 | 29 | tmp := Unwrap(kek,ctext) 30 | t.Logf("HAVE %x WANT %x",tmp,key) 31 | if !bytes.Equal(tmp,key) { 32 | t.Error("unwrap failed") 33 | } 34 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Packages asn1/encoding and crypto/gcm are Copyright (c) 2009 The Go Authors, with a BSD 2 | license. See the license files in those directories for details. 3 | 4 | The rest of the code (my original code) falls under MIT license: 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2016 Steve Dunham 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | -------------------------------------------------------------------------------- /crypto/gcm/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /encoding/asn1/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /crypto/gcm/xor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 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 gcm 6 | 7 | import ( 8 | "runtime" 9 | "unsafe" 10 | ) 11 | 12 | const wordSize = int(unsafe.Sizeof(uintptr(0))) 13 | const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" 14 | 15 | // fastXORBytes xors in bulk. It only works on architectures that 16 | // support unaligned read/writes. 17 | func fastXORBytes(dst, a, b []byte) int { 18 | n := len(a) 19 | if len(b) < n { 20 | n = len(b) 21 | } 22 | 23 | w := n / wordSize 24 | if w > 0 { 25 | dw := *(*[]uintptr)(unsafe.Pointer(&dst)) 26 | aw := *(*[]uintptr)(unsafe.Pointer(&a)) 27 | bw := *(*[]uintptr)(unsafe.Pointer(&b)) 28 | for i := 0; i < w; i++ { 29 | dw[i] = aw[i] ^ bw[i] 30 | } 31 | } 32 | 33 | for i := (n - n%wordSize); i < n; i++ { 34 | dst[i] = a[i] ^ b[i] 35 | } 36 | 37 | return n 38 | } 39 | 40 | func safeXORBytes(dst, a, b []byte) int { 41 | n := len(a) 42 | if len(b) < n { 43 | n = len(b) 44 | } 45 | for i := 0; i < n; i++ { 46 | dst[i] = a[i] ^ b[i] 47 | } 48 | return n 49 | } 50 | 51 | // xorBytes xors the bytes in a and b. The destination is assumed to have enough 52 | // space. Returns the number of bytes xor'd. 53 | func xorBytes(dst, a, b []byte) int { 54 | if supportsUnaligned { 55 | return fastXORBytes(dst, a, b) 56 | } else { 57 | // TODO(hanwen): if (dst, a, b) have common alignment 58 | // we could still try fastXORBytes. It is not clear 59 | // how often this happens, and it's only worth it if 60 | // the block encryption itself is hardware 61 | // accelerated. 62 | return safeXORBytes(dst, a, b) 63 | } 64 | } 65 | 66 | // fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.) 67 | // The arguments are assumed to be of equal length. 68 | func fastXORWords(dst, a, b []byte) { 69 | dw := *(*[]uintptr)(unsafe.Pointer(&dst)) 70 | aw := *(*[]uintptr)(unsafe.Pointer(&a)) 71 | bw := *(*[]uintptr)(unsafe.Pointer(&b)) 72 | n := len(b) / wordSize 73 | for i := 0; i < n; i++ { 74 | dw[i] = aw[i] ^ bw[i] 75 | } 76 | } 77 | 78 | func xorWords(dst, a, b []byte) { 79 | if supportsUnaligned { 80 | fastXORWords(dst, a, b) 81 | } else { 82 | safeXORBytes(dst, a, b) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /crypto/aeswrap/aeswrap.go: -------------------------------------------------------------------------------- 1 | // Implements rfc3394 - AES keywrapping. 2 | package aeswrap 3 | 4 | import ( 5 | "bytes" 6 | "crypto/aes" 7 | ) 8 | 9 | var rfc3394iv = []byte{0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6} 10 | 11 | // Wrap will wrap 'in' with the key in 'kek'. 12 | func Wrap(kek []byte, in []byte) []byte { 13 | // 1) Initialize variables. 14 | // Set A = IV, an initial value (see 2.2.3) 15 | // For i = 1 to n 16 | // R[i] = P[i] 17 | 18 | var A, B, R []byte 19 | A = make([]byte, 8) 20 | B = make([]byte, 16) 21 | R = make([]byte, len(in)+8) 22 | 23 | copy(A, rfc3394iv) 24 | copy(R[8:], in) 25 | 26 | n := len(in) / 8 27 | cipher, err := aes.NewCipher(kek) 28 | if err != nil { 29 | return nil 30 | } 31 | 32 | // 2) Calculate intermediate values. 33 | // 34 | // For j = 0 to 5 35 | // For i=1 to n 36 | // B = AES(K, A | R[i]) 37 | // A = MSB(64, B) ^ t where t = (n*j)+i 38 | // R[i] = LSB(64, B) 39 | for j := 0; j <= 5; j++ { 40 | for i := 1; i <= n; i++ { 41 | copy(B, A) 42 | copy(B[8:], R[8*i:]) 43 | cipher.Encrypt(B, B) 44 | copy(A, B) 45 | t := (n * j) + i 46 | if t > 255 { 47 | panic("IMPLEMENT") 48 | } 49 | A[7] ^= byte(t & 255) 50 | copy(R[8*i:], B[8:]) 51 | } 52 | } 53 | 54 | // 3) Output the results. 55 | // 56 | // Set C[0] = A 57 | // For i = 1 to n 58 | // C[i] = R[i] 59 | copy(R, A) 60 | return R 61 | } 62 | 63 | // Unwrap will unwap the value in "in" with the key "kek". Returns nil on failure. 64 | func Unwrap(kek []byte, in []byte) []byte { 65 | // TODO add a few more checks.. 66 | if len(kek) < 16 || len(in)%8 != 0 { 67 | return nil 68 | } 69 | 70 | // 1) Initialize variables. 71 | // 72 | // Set A = C[0] 73 | // For i = 1 to n 74 | // R[i] = C[i] 75 | var A, B, R []byte 76 | A = make([]byte, 8) 77 | B = make([]byte, 16) 78 | R = make([]byte, len(in)) 79 | 80 | copy(A, in) 81 | copy(R, in) 82 | 83 | cipher, err := aes.NewCipher(kek) 84 | if err != nil { 85 | return nil 86 | } 87 | 88 | // 2) Compute intermediate values. 89 | // 90 | // For j = 5 to 0 91 | // For i = n to 1 92 | // B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i 93 | // A = MSB(64, B) 94 | // R[i] = LSB(64, B) 95 | n := len(in)/8 - 1 96 | for j := 5; j >= 0; j-- { 97 | for i := n; i > 0; i-- { 98 | // OPERATION 99 | 100 | copy(B, A) 101 | copy(B[8:], R[i*8:]) 102 | t := uint64(n*j + i) 103 | if t > 255 { 104 | panic("IMPLEMENT") 105 | } 106 | B[7] ^= uint8(t & 0xff) 107 | cipher.Decrypt(B, B) 108 | copy(A, B) 109 | copy(R[i*8:], B[8:]) 110 | } 111 | } 112 | 113 | // 3) Output results. 114 | // 115 | // If A is an appropriate initial value (see 2.2.3), 116 | // Then 117 | // For i = 1 to n 118 | // P[i] = R[i] 119 | // Else 120 | // Return an error 121 | if !bytes.Equal(A, rfc3394iv) { 122 | return nil 123 | } 124 | return R[8:] 125 | } 126 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS Backup Extraction 2 | 3 | This repository contains `irestore`, a program for inspecting and pulling files and the keychain out of an encrypted iOS backup tree. It is written in Go and based on work done in the `iphone-dataprotection` project found on google code. 4 | 5 | If you are using an encrypted backup, it also can read parts of the keychain and dump it as json. 6 | 7 | Without options, `irestore` will list the current backups found on your machine. You may reference a backup by name or guid. 8 | 9 | ```shell 10 | # irestore 11 | MyPhone 5069636b6c656448657272696e674170706c6573 12 | MyPad 43686f636f6c61746552616d656b696e73546f6f 13 | ``` 14 | 15 | The first argument is the device id or device name: 16 | 17 | ```shell 18 | # irestore MyPad 19 | Selected MyPad 43686f636f6c61746552616d656b696e73546f6f 20 | Usage: 21 | ls [domain] 22 | restore domain dest 23 | dumpkeys [outputfile] 24 | apps 25 | ``` 26 | 27 | The `ls` command will list domains or files in a domain. 28 | 29 | The `restore` command will restore the files in a domain into a directory tree. 30 | 31 | The `dumpkeys` command will dump the readable portions of the keychain to json. 32 | 33 | The `apps` command will list the installed apps. 34 | 35 | _Changes to the database format in recent iOS releases:_ 36 | 37 | ## iOS 10 (deprecated) 38 | 39 | iOS 10 is using a different format for the manifest. It stores the data in a sqlite3 database called `Manifest.db`, which contains two tables. And the actual files themselves are moved to subdirectories whose names are the first two characters of the filename. 40 | 41 | ### Properties 42 | 43 | The `Properties` table contains a list of key/value pairs. The key `salt` contains the salt for the backup password. 44 | The key `passwordHash` contains `sha256(password||salt)`. 45 | 46 | ### Files 47 | 48 | The `Files` table contains a row for each file. The columns are `fileID`, `domain`, `relativePath`, `flags`, and `file`. The `fileID` is the hash of `domain + "-" + relativePath`. 49 | 50 | The `file` field is an encrypted with AES128-CBC. The key is the first 16 bytes of `sha1(password||salt)`, the initialization vector is the sequence of bytes `0, 1, 2, ..., 15`. 51 | 52 | The decrypted data is a binary plist, specifically a key-valued archive of a `MBFile` object. This object has a `ProtectionClass` field that gives the files protection class (used for choosing an appropriate key from the keybag) and an `EncryptionKey` field containing an `NSMutableData` with the same format as the encryption key in the MBDB file. (A little endian uint32 containing the protection class, followed by the file's key AES-WRAPed by the key for that protection class.) 53 | 54 | ## iOS 10.1 55 | 56 | The properties table described above is now empty, and the "file" column is a bare plist. To keep the code simple, I no longer support the iOS 10.0 57 | backup format. 58 | 59 | 60 | ## iOS 10.2 61 | 62 | There are a few changes in iOS 10.2. The Manifest database itself is encrypted, its key is stored, wrapped with protection class 4, in the `ManifestKey` property `Manifest.plist`. This necessitates asking for the password before listing files. 63 | 64 | Further, the keybag has a second round of PBKDF2 with different parameters and a sha256 hash function. This one takes about 10 seconds in Go, so the code now prints the decrypted key in hex. If you provide this hex key instead of your password, you can skip the long key derivation step. 65 | 66 | (iOS 10.2 details came from a github thread.) -------------------------------------------------------------------------------- /kvarchive/keyed.go: -------------------------------------------------------------------------------- 1 | // Package kvarchive will deserialize a key/value archive into generic objects. 2 | // 3 | // This is an old work in progress package. I intended to eventually allow unmarshalling into 4 | // structs, but got side tracked. Then needed this code for the "irestore" stuff. 5 | // 6 | // There is a lot of stuff I've learned from writing a python version of this that hasn't made it into 7 | // here yet. 8 | // 9 | package kvarchive 10 | 11 | import ( 12 | "errors" 13 | "fmt" 14 | "io" 15 | "os" 16 | 17 | "github.com/dunhamsteve/plist" 18 | // "encoding/json" 19 | ) 20 | 21 | func must(err error) { 22 | if err != nil { 23 | fmt.Println(err) 24 | os.Exit(-1) 25 | } 26 | } 27 | 28 | type KVArchiveTop struct { 29 | Root plist.UID 30 | } 31 | 32 | type KVArchive struct { 33 | Archiver string `plist:"$archiver"` 34 | Top KVArchiveTop `plist:"$top"` 35 | Objects []interface{} `plist:"$objects"` 36 | Version int `plist:"$version"` 37 | objects map[int]interface{} 38 | } 39 | 40 | func (kv *KVArchive) coerce(v interface{}) interface{} { 41 | switch v.(type) { 42 | case plist.UID: 43 | return kv.GetObject(v.(plist.UID)) 44 | } 45 | return v 46 | } 47 | 48 | func (kv *KVArchive) GetObject(uid plist.UID) interface{} { 49 | v := kv.Objects[uid.Value()] 50 | if s, ok := v.(string); ok && s == "$null" { 51 | return nil 52 | } 53 | if m, ok := v.(map[string]interface{}); ok { 54 | var className string 55 | c := kv.Objects[m["$class"].(plist.UID).Value()] 56 | className = c.(map[string]interface{})["$classname"].(string) 57 | 58 | // fmt.Println("className", className, v) 59 | switch className { 60 | case "NSMutableDictionary", "NSDictionary": 61 | keys := m["NS.keys"].([]interface{}) 62 | values := m["NS.objects"].([]interface{}) 63 | rval := make(map[interface{}]interface{}) 64 | for i, _key := range keys { 65 | key := kv.coerce(_key) 66 | value := kv.coerce(values[i]) 67 | rval[key] = value 68 | } 69 | return rval 70 | case "NSMutableData", "NSData": 71 | return m["NS.data"] 72 | case "NSMutableArray", "NSArray": 73 | values := m["NS.objects"].([]interface{}) 74 | rval := make([]interface{}, len(values)) 75 | for i, v := range values { 76 | rval[i] = kv.coerce(v) 77 | } 78 | return rval 79 | case "NSMutableString", "NSString": 80 | return m["NS.string"] 81 | case "NSDecimalNumberPlaceholder": 82 | bb := m["NS.mantissa"].([]byte) 83 | bo := m["NS.mantissa.bo"].(int64) 84 | l := 1 << uint(m["NS.length"].(int64)) 85 | 86 | // fmt.Printf("% x %d, %d\n", bb, bo, l) 87 | var value int64 88 | for i := 0; i < l; i++ { 89 | if bo == 0 { 90 | value = value<<8 | int64(bb[i]) 91 | } else { 92 | value |= int64(bb[i]) << uint(8*i) 93 | } 94 | } 95 | return value 96 | case "NSDate": 97 | stamp := int64(m["NS.time"].(float64)) + 978307200 98 | 99 | return stamp 100 | default: 101 | // fmt.Println("Unhandled class", className) // for debugging, but noisy 102 | 103 | rval := make(map[string]interface{}) 104 | rval["_type"] = className 105 | for k, v := range m { 106 | if k[0] != '$' { 107 | rval[k] = kv.coerce(v) 108 | } 109 | } 110 | return rval 111 | } 112 | } 113 | return v 114 | } 115 | 116 | // UnArchive deserializes a plist into a graph of generic objects (maps/arrays/etc.) 117 | func UnArchive(r io.ReadSeeker) (rval interface{}, err error) { 118 | data := new(KVArchive) 119 | data.objects = make(map[int]interface{}) 120 | err = plist.Unmarshal(r, data) 121 | if err != nil { 122 | return 123 | } 124 | if data.Archiver != "NSKeyedArchiver" { 125 | return nil, errors.New("Not a NSKeyedArchiver archiver") 126 | } 127 | ruid := data.Top.Root 128 | rval = data.GetObject(ruid) 129 | return 130 | } 131 | -------------------------------------------------------------------------------- /keybag/keybag.go: -------------------------------------------------------------------------------- 1 | // This has been run against a keybag from Manifest.plist in an iOS backup. 2 | // It will probably need work to handle other keybag variants. 3 | // 4 | // /var/db/lockdown plists appear to no longer contain keybags. (And 0x835 was needed to decrypt them anyway.) 5 | // 6 | package keybag 7 | 8 | import ( 9 | "crypto/sha1" 10 | "crypto/sha256" 11 | "encoding/binary" 12 | "errors" 13 | "fmt" 14 | "log" 15 | 16 | "encoding/hex" 17 | 18 | "time" 19 | 20 | "github.com/dunhamsteve/ios/crypto/aeswrap" 21 | "golang.org/x/crypto/pbkdf2" 22 | ) 23 | 24 | type Key struct { 25 | UUID []byte 26 | Class uint32 27 | Wrap uint32 28 | KeyType uint32 29 | WrappedKey []byte 30 | Key []byte 31 | } 32 | 33 | type Keybag struct { 34 | Version uint32 35 | Type uint32 36 | 37 | UUID []byte 38 | HMAC []byte 39 | Wrap uint32 40 | Salt []byte 41 | Iter uint32 42 | AuxSalt []byte 43 | AuxIter uint32 44 | Keys []*Key 45 | } 46 | 47 | var be = binary.BigEndian 48 | 49 | func Read(data []byte) Keybag { 50 | var kb Keybag 51 | var key *Key 52 | var state = 0 53 | 54 | for pos := 0; pos+8 < len(data); { 55 | fourcc := string(data[pos : pos+4]) 56 | size := int(be.Uint32(data[pos+4 : pos+8])) 57 | pos += 8 58 | value := data[pos : pos+size] 59 | var ivalue uint32 60 | pos += size 61 | if size == 4 { 62 | ivalue = be.Uint32(value[:4]) 63 | } 64 | 65 | // UUID appears once in the top matter, then once per entry thereafter. 66 | if state < 2 { 67 | switch fourcc { 68 | case "VERS": 69 | kb.Version = ivalue 70 | case "TYPE": 71 | kb.Type = ivalue 72 | case "WRAP": 73 | kb.Wrap = ivalue 74 | case "HMCK": 75 | kb.HMAC = value 76 | case "SALT": 77 | kb.Salt = value 78 | case "ITER": 79 | kb.Iter = ivalue 80 | case "DPWT": 81 | // not sure what this one is 82 | case "DPIC": 83 | kb.AuxIter = ivalue 84 | case "DPSL": 85 | kb.AuxSalt = value 86 | case "UUID": 87 | state++ 88 | if state == 2 { 89 | // Rewind position to let the UUID show up again 90 | pos -= 8 + size 91 | } else { 92 | kb.UUID = value 93 | } 94 | default: 95 | log.Fatalln("fourcc", fourcc, "not handled", len(value), hex.EncodeToString(value)) 96 | } 97 | } else { 98 | switch fourcc { 99 | case "UUID": 100 | key = new(Key) 101 | kb.Keys = append(kb.Keys, key) 102 | key.UUID = value 103 | case "CLAS": 104 | key.Class = ivalue 105 | case "WRAP": 106 | key.Wrap = ivalue 107 | case "KTYP": 108 | key.KeyType = ivalue 109 | case "WPKY": 110 | key.WrappedKey = value 111 | default: 112 | log.Fatal("fourcc ", fourcc, " not handled") 113 | } 114 | } 115 | } 116 | return kb 117 | } 118 | 119 | // Get a class key, or nil if not available 120 | func (kb *Keybag) GetClassKey(class uint32) []byte { 121 | for _, key := range kb.Keys { 122 | if key.Class == class { 123 | return key.Key 124 | } 125 | } 126 | return nil 127 | } 128 | 129 | // SetPassword decrypts the keybag, recovering some of the keys. 130 | func (kb *Keybag) SetPassword(password string) error { 131 | var passkey = []byte(password) 132 | if len(password) == 64 { 133 | passkey, _ = hex.DecodeString(password) 134 | } else { 135 | start := time.Now() 136 | if kb.AuxIter > 0 { 137 | passkey = pbkdf2.Key(passkey, kb.AuxSalt, int(kb.AuxIter), 32, sha256.New) 138 | } 139 | passkey = pbkdf2.Key(passkey, kb.Salt, int(kb.Iter), 32, sha1.New) 140 | fmt.Println("key derivation took", time.Now().Sub(start), "use the password", hex.EncodeToString(passkey), "to skip") 141 | } 142 | 143 | for _, key := range kb.Keys { 144 | if key.Wrap == 2 { // 3 means we need 0x835 too, 1 means only 0x835 145 | key.Key = aeswrap.Unwrap(passkey, key.WrappedKey) 146 | if key.Key == nil { 147 | return errors.New("Bad password") 148 | } 149 | } 150 | } 151 | return nil 152 | } 153 | -------------------------------------------------------------------------------- /encoding/asn1/marshal_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 asn1 6 | 7 | import ( 8 | "bytes" 9 | "encoding/hex" 10 | "math/big" 11 | "testing" 12 | "time" 13 | ) 14 | 15 | type intStruct struct { 16 | A int 17 | } 18 | 19 | type twoIntStruct struct { 20 | A int 21 | B int 22 | } 23 | 24 | type bigIntStruct struct { 25 | A *big.Int 26 | } 27 | 28 | type nestedStruct struct { 29 | A intStruct 30 | } 31 | 32 | type rawContentsStruct struct { 33 | Raw RawContent 34 | A int 35 | } 36 | 37 | type implicitTagTest struct { 38 | A int `asn1:"implicit,tag:5"` 39 | } 40 | 41 | type explicitTagTest struct { 42 | A int `asn1:"explicit,tag:5"` 43 | } 44 | 45 | type flagTest struct { 46 | A Flag `asn1:"tag:0,optional"` 47 | } 48 | 49 | type generalizedTimeTest struct { 50 | A time.Time `asn1:"generalized"` 51 | } 52 | 53 | type ia5StringTest struct { 54 | A string `asn1:"ia5"` 55 | } 56 | 57 | type printableStringTest struct { 58 | A string `asn1:"printable"` 59 | } 60 | 61 | type optionalRawValueTest struct { 62 | A RawValue `asn1:"optional"` 63 | } 64 | 65 | type omitEmptyTest struct { 66 | A []string `asn1:"omitempty"` 67 | } 68 | 69 | type defaultTest struct { 70 | A int `asn1:"optional,default:1"` 71 | } 72 | 73 | type testSET []int 74 | 75 | var PST = time.FixedZone("PST", -8*60*60) 76 | 77 | type marshalTest struct { 78 | in interface{} 79 | out string // hex encoded 80 | } 81 | 82 | func farFuture() time.Time { 83 | t, err := time.Parse(time.RFC3339, "2100-04-05T12:01:01Z") 84 | if err != nil { 85 | panic(err) 86 | } 87 | return t 88 | } 89 | 90 | var marshalTests = []marshalTest{ 91 | {10, "02010a"}, 92 | {127, "02017f"}, 93 | {128, "02020080"}, 94 | {-128, "020180"}, 95 | {-129, "0202ff7f"}, 96 | {intStruct{64}, "3003020140"}, 97 | {bigIntStruct{big.NewInt(0x123456)}, "30050203123456"}, 98 | {twoIntStruct{64, 65}, "3006020140020141"}, 99 | {nestedStruct{intStruct{127}}, "3005300302017f"}, 100 | {[]byte{1, 2, 3}, "0403010203"}, 101 | {implicitTagTest{64}, "3003850140"}, 102 | {explicitTagTest{64}, "3005a503020140"}, 103 | {flagTest{true}, "30028000"}, 104 | {flagTest{false}, "3000"}, 105 | {time.Unix(0, 0).UTC(), "170d3730303130313030303030305a"}, 106 | {time.Unix(1258325776, 0).UTC(), "170d3039313131353232353631365a"}, 107 | {time.Unix(1258325776, 0).In(PST), "17113039313131353134353631362d30383030"}, 108 | {farFuture(), "180f32313030303430353132303130315a"}, 109 | {generalizedTimeTest{time.Unix(1258325776, 0).UTC()}, "3011180f32303039313131353232353631365a"}, 110 | {BitString{[]byte{0x80}, 1}, "03020780"}, 111 | {BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"}, 112 | {ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"}, 113 | {ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"}, 114 | {ObjectIdentifier([]int{2, 100, 3}), "0603813403"}, 115 | {"test", "130474657374"}, 116 | { 117 | "" + 118 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + 119 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + 120 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + 121 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 127 times 'x' 122 | "137f" + 123 | "7878787878787878787878787878787878787878787878787878787878787878" + 124 | "7878787878787878787878787878787878787878787878787878787878787878" + 125 | "7878787878787878787878787878787878787878787878787878787878787878" + 126 | "78787878787878787878787878787878787878787878787878787878787878", 127 | }, 128 | { 129 | "" + 130 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + 131 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + 132 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + 133 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // This is 128 times 'x' 134 | "138180" + 135 | "7878787878787878787878787878787878787878787878787878787878787878" + 136 | "7878787878787878787878787878787878787878787878787878787878787878" + 137 | "7878787878787878787878787878787878787878787878787878787878787878" + 138 | "7878787878787878787878787878787878787878787878787878787878787878", 139 | }, 140 | {ia5StringTest{"test"}, "3006160474657374"}, 141 | {optionalRawValueTest{}, "3000"}, 142 | {printableStringTest{"test"}, "3006130474657374"}, 143 | {printableStringTest{"test*"}, "30071305746573742a"}, 144 | {rawContentsStruct{nil, 64}, "3003020140"}, 145 | {rawContentsStruct{[]byte{0x30, 3, 1, 2, 3}, 64}, "3003010203"}, 146 | {RawValue{Tag: 1, Class: 2, IsCompound: false, Bytes: []byte{1, 2, 3}}, "8103010203"}, 147 | {testSET([]int{10}), "310302010a"}, 148 | {omitEmptyTest{[]string{}}, "3000"}, 149 | {omitEmptyTest{[]string{"1"}}, "30053003130131"}, 150 | {"Σ", "0c02cea3"}, 151 | {defaultTest{0}, "3003020100"}, 152 | {defaultTest{1}, "3000"}, 153 | {defaultTest{2}, "3003020102"}, 154 | } 155 | 156 | func TestMarshal(t *testing.T) { 157 | for i, test := range marshalTests { 158 | data, err := Marshal(test.in) 159 | if err != nil { 160 | t.Errorf("#%d failed: %s", i, err) 161 | } 162 | out, _ := hex.DecodeString(test.out) 163 | if !bytes.Equal(out, data) { 164 | t.Errorf("#%d got: %x want %x\n\t%q\n\t%q", i, data, out, data, out) 165 | 166 | } 167 | } 168 | } 169 | 170 | func TestInvalidUTF8(t *testing.T) { 171 | _, err := Marshal(string([]byte{0xff, 0xff})) 172 | if err == nil { 173 | t.Errorf("invalid UTF8 string was accepted") 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /encoding/asn1/common.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 asn1 6 | 7 | import ( 8 | "reflect" 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | // ASN.1 objects have metadata preceding them: 14 | // the tag: the type of the object 15 | // a flag denoting if this object is compound or not 16 | // the class type: the namespace of the tag 17 | // the length of the object, in bytes 18 | 19 | // Here are some standard tags and classes 20 | 21 | // ASN.1 tags represent the type of the following object. 22 | const ( 23 | TagBoolean = 1 24 | TagInteger = 2 25 | TagBitString = 3 26 | TagOctetString = 4 27 | TagOID = 6 28 | TagEnum = 10 29 | TagUTF8String = 12 30 | TagSequence = 16 31 | TagSet = 17 32 | TagPrintableString = 19 33 | TagT61String = 20 34 | TagIA5String = 22 35 | TagUTCTime = 23 36 | TagGeneralizedTime = 24 37 | TagGeneralString = 27 38 | ) 39 | 40 | // ASN.1 class types represent the namespace of the tag. 41 | const ( 42 | ClassUniversal = 0 43 | ClassApplication = 1 44 | ClassContextSpecific = 2 45 | ClassPrivate = 3 46 | ) 47 | 48 | type tagAndLength struct { 49 | class, tag, length int 50 | isCompound bool 51 | } 52 | 53 | // ASN.1 has IMPLICIT and EXPLICIT tags, which can be translated as "instead 54 | // of" and "in addition to". When not specified, every primitive type has a 55 | // default tag in the UNIVERSAL class. 56 | // 57 | // For example: a BIT STRING is tagged [UNIVERSAL 3] by default (although ASN.1 58 | // doesn't actually have a UNIVERSAL keyword). However, by saying [IMPLICIT 59 | // CONTEXT-SPECIFIC 42], that means that the tag is replaced by another. 60 | // 61 | // On the other hand, if it said [EXPLICIT CONTEXT-SPECIFIC 10], then an 62 | // /additional/ tag would wrap the default tag. This explicit tag will have the 63 | // compound flag set. 64 | // 65 | // (This is used in order to remove ambiguity with optional elements.) 66 | // 67 | // You can layer EXPLICIT and IMPLICIT tags to an arbitrary depth, however we 68 | // don't support that here. We support a single layer of EXPLICIT or IMPLICIT 69 | // tagging with tag strings on the fields of a structure. 70 | 71 | // fieldParameters is the parsed representation of tag string from a structure field. 72 | type fieldParameters struct { 73 | optional bool // true iff the field is OPTIONAL 74 | explicit bool // true iff an EXPLICIT tag is in use. 75 | application bool // true iff an APPLICATION tag is in use. 76 | defaultValue *int64 // a default value for INTEGER typed fields (maybe nil). 77 | tag *int // the EXPLICIT or IMPLICIT tag (maybe nil). 78 | stringType int // the string tag to use when marshaling. 79 | timeType int // the time tag to use when marshaling. 80 | set bool // true iff this should be encoded as a SET 81 | omitEmpty bool // true iff this should be omitted if empty when marshaling. 82 | 83 | // Invariants: 84 | // if explicit is set, tag is non-nil. 85 | } 86 | 87 | // Given a tag string with the format specified in the package comment, 88 | // parseFieldParameters will parse it into a fieldParameters structure, 89 | // ignoring unknown parts of the string. 90 | func parseFieldParameters(str string) (ret fieldParameters) { 91 | for _, part := range strings.Split(str, ",") { 92 | switch { 93 | case part == "optional": 94 | ret.optional = true 95 | case part == "explicit": 96 | ret.explicit = true 97 | if ret.tag == nil { 98 | ret.tag = new(int) 99 | } 100 | case part == "generalized": 101 | ret.timeType = TagGeneralizedTime 102 | case part == "utc": 103 | ret.timeType = TagUTCTime 104 | case part == "ia5": 105 | ret.stringType = TagIA5String 106 | case part == "printable": 107 | ret.stringType = TagPrintableString 108 | case part == "utf8": 109 | ret.stringType = TagUTF8String 110 | case strings.HasPrefix(part, "default:"): 111 | i, err := strconv.ParseInt(part[8:], 10, 64) 112 | if err == nil { 113 | ret.defaultValue = new(int64) 114 | *ret.defaultValue = i 115 | } 116 | case strings.HasPrefix(part, "tag:"): 117 | i, err := strconv.Atoi(part[4:]) 118 | if err == nil { 119 | ret.tag = new(int) 120 | *ret.tag = i 121 | } 122 | case part == "set": 123 | ret.set = true 124 | case part == "application": 125 | ret.application = true 126 | if ret.tag == nil { 127 | ret.tag = new(int) 128 | } 129 | case part == "omitempty": 130 | ret.omitEmpty = true 131 | } 132 | } 133 | return 134 | } 135 | 136 | // Given a reflected Go type, getUniversalType returns the default tag number 137 | // and expected compound flag. 138 | func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) { 139 | switch t { 140 | case objectIdentifierType: 141 | return TagOID, false, true 142 | case bitStringType: 143 | return TagBitString, false, true 144 | case timeType: 145 | return TagUTCTime, false, true 146 | case enumeratedType: 147 | return TagEnum, false, true 148 | case bigIntType: 149 | return TagInteger, false, true 150 | } 151 | switch t.Kind() { 152 | case reflect.Bool: 153 | return TagBoolean, false, true 154 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 155 | return TagInteger, false, true 156 | case reflect.Struct: 157 | return TagSequence, true, true 158 | case reflect.Slice: 159 | if t.Elem().Kind() == reflect.Uint8 { 160 | return TagOctetString, false, true 161 | } 162 | if strings.HasSuffix(t.Name(), "SET") { 163 | return TagSet, true, true 164 | } 165 | return TagSequence, true, true 166 | case reflect.String: 167 | return TagPrintableString, false, true 168 | } 169 | return 0, false, false 170 | } 171 | -------------------------------------------------------------------------------- /cmd/irestore/irestore.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/binary" 5 | "encoding/json" 6 | "time" 7 | 8 | "bytes" 9 | "fmt" 10 | "io" 11 | "io/ioutil" 12 | "log" 13 | "os" 14 | "path" 15 | "strings" 16 | "syscall" 17 | 18 | "crypto/aes" 19 | 20 | "github.com/dunhamsteve/ios/backup" 21 | "github.com/dunhamsteve/ios/crypto/aeswrap" 22 | "github.com/dunhamsteve/ios/crypto/gcm" 23 | "github.com/dunhamsteve/ios/encoding/asn1" 24 | "github.com/dunhamsteve/plist" 25 | "golang.org/x/crypto/ssh/terminal" 26 | ) 27 | 28 | // Quick and Dirty error handling - when I don't expect an error, but want to know if it happens 29 | func must(err error) { 30 | if err != nil { 31 | log.Fatal(err) 32 | } 33 | } 34 | 35 | func dumpJSON(x interface{}) { 36 | json, err := json.MarshalIndent(x, "", " ") 37 | must(err) 38 | fmt.Println(string(json)) 39 | } 40 | 41 | func getpass() string { 42 | fmt.Fprint(os.Stderr, "Backup Password: ") 43 | pw, err := terminal.ReadPassword(int(syscall.Stdin)) 44 | must(err) 45 | fmt.Println() 46 | return string(pw) 47 | } 48 | 49 | func domains(db *backup.MobileBackup) { 50 | for _, domain := range db.Domains() { 51 | fmt.Println(domain) 52 | } 53 | } 54 | func apps(db *backup.MobileBackup) { 55 | for app := range db.Manifest.Applications { 56 | fmt.Println(app) 57 | } 58 | } 59 | 60 | func list(db *backup.MobileBackup, domain string) { 61 | for _, rec := range db.Records { 62 | // just files for now 63 | if rec.Length > 0 { 64 | if domain == "*" { 65 | fmt.Println(rec.Domain, rec.Path) 66 | } else if domain == rec.Domain { 67 | fmt.Println(rec.Path) 68 | } 69 | } 70 | } 71 | } 72 | 73 | type KCEntry struct { 74 | Data []byte `plist:"v_Data"` 75 | Ref []byte `plist:"v_PersistentRef"` 76 | } 77 | 78 | type Keychain struct { 79 | Internet []KCEntry `plist:"inet"` 80 | General []KCEntry `plist:"genp"` 81 | Certs []KCEntry `plist:"cert"` 82 | Keys []KCEntry `plist:"keys"` 83 | } 84 | 85 | var le = binary.LittleEndian 86 | 87 | // Mostly works, but I don't think time is getting populated. 88 | type Entry struct { 89 | Raw asn1.RawContent 90 | Key string 91 | Value interface{} 92 | } 93 | 94 | type DateEntry struct { 95 | Key string 96 | Time time.Time 97 | } 98 | 99 | type EntrySET []Entry 100 | 101 | func parseRecord(data []byte) map[string]interface{} { 102 | var v EntrySET 103 | rval := make(map[string]interface{}) 104 | _, err := asn1.Unmarshal(data, &v) 105 | if err != nil { 106 | fmt.Println(err) 107 | ioutil.WriteFile("failed.bin", data, 0644) 108 | } 109 | // must(err) 110 | for _, entry := range v { 111 | // Time values come through as nil, so we try again with a "DateEntry" structure. 112 | if entry.Value == nil { 113 | var entry2 DateEntry 114 | _, err := asn1.Unmarshal(entry.Raw, &entry2) 115 | if err == nil { 116 | entry.Value = entry2.Time 117 | } 118 | } 119 | 120 | rval[entry.Key] = entry.Value 121 | } 122 | return rval 123 | } 124 | 125 | func dumpKeyGroup(db *backup.MobileBackup, group []KCEntry) []interface{} { 126 | var rval []interface{} 127 | for _, key := range group { 128 | version := le.Uint32(key.Data) 129 | class := le.Uint32(key.Data[4:]) 130 | switch version { 131 | case 3: 132 | l := le.Uint32(key.Data[8:]) 133 | wkey := key.Data[12 : 12+l] 134 | edata := key.Data[12+l:] 135 | 136 | // Find key for class 137 | ckey := db.Keybag.GetClassKey(class) 138 | if ckey == nil { 139 | fmt.Println("No key for class", class, string(key.Ref)[:4], key.Ref[4:]) 140 | continue 141 | } 142 | 143 | key := aeswrap.Unwrap(ckey, wkey) 144 | if key == nil { 145 | fmt.Println("unwrap failed for class", class) 146 | continue 147 | } 148 | // Create a gcm cipher 149 | c, err := aes.NewCipher(key) 150 | if err != nil { 151 | log.Panic(err) 152 | } 153 | gcm, err := gcm.NewGCM(c) 154 | if err != nil { 155 | log.Panic(err) 156 | } 157 | plain, err := gcm.Open(nil, nil, edata, nil) 158 | must(err) 159 | record := parseRecord(plain) 160 | rval = append(rval, record) 161 | default: 162 | panic(fmt.Sprintf("Unhandled keychain blob version %d", version)) 163 | } 164 | } 165 | 166 | return rval 167 | } 168 | 169 | func dumpkeys(db *backup.MobileBackup, outfile string) { 170 | for _, rec := range db.Records { 171 | if rec.Domain == "KeychainDomain" && rec.Path == "keychain-backup.plist" { 172 | fmt.Println(rec) 173 | data, err := db.ReadFile(rec) 174 | must(err) 175 | ioutil.WriteFile("kcb.plist", data, 0x644) 176 | 177 | fmt.Println("read", len(data)) 178 | var v Keychain 179 | err = plist.Unmarshal(bytes.NewReader(data), &v) 180 | must(err) 181 | 182 | dump := make(map[string][]interface{}) 183 | dump["General"] = dumpKeyGroup(db, v.General) 184 | dump["Internet"] = dumpKeyGroup(db, v.Internet) 185 | dump["Certs"] = dumpKeyGroup(db, v.Certs) 186 | dump["Keys"] = dumpKeyGroup(db, v.Keys) 187 | s, err := json.MarshalIndent(dump, "", " ") 188 | must(err) 189 | if outfile != "" { 190 | err = ioutil.WriteFile(outfile, s, 0644) 191 | must(err) 192 | } else { 193 | _, err = os.Stdout.Write(s) 194 | must(err) 195 | } 196 | } 197 | } 198 | } 199 | 200 | func restore(db *backup.MobileBackup, domain string, dest string) { 201 | var err error 202 | var total int64 203 | for _, rec := range db.Records { 204 | if rec.Length > 0 { 205 | var outPath string 206 | if domain == "*" { 207 | outPath = path.Join(dest, rec.Domain, rec.Path) 208 | } else if rec.Domain == domain { 209 | outPath = path.Join(dest, rec.Path) 210 | } 211 | 212 | if outPath != "" { 213 | fmt.Println(rec.Path) 214 | 215 | dir := path.Dir(outPath) 216 | err = os.MkdirAll(dir, 0755) 217 | must(err) 218 | r, err := db.FileReader(rec) 219 | if err != nil { 220 | log.Println("error reading file", rec, err) 221 | continue 222 | } 223 | must(err) 224 | w, err := os.Create(outPath) 225 | must(err) 226 | n, err := io.Copy(w, r) 227 | total += n 228 | r.Close() 229 | w.Close() 230 | } 231 | } 232 | } 233 | fmt.Println("Wrote", total, "bytes") 234 | } 235 | 236 | func main() { 237 | // first component is udid 238 | mm, err := backup.Enumerate() 239 | must(err) 240 | 241 | var selected *backup.Backup 242 | 243 | if len(os.Args) > 1 { 244 | key := os.Args[1] 245 | for _, man := range mm { 246 | dashed := strings.Contains(man.FileName, "-") 247 | if man.DeviceName == key && !dashed { 248 | selected = &man 249 | break 250 | } 251 | if man.FileName == key { 252 | selected = &man 253 | break 254 | } 255 | if strings.Contains(man.DeviceName, key) && !dashed { 256 | selected = &man 257 | break 258 | } 259 | if strings.Contains(man.FileName, key) && !dashed { 260 | selected = &man 261 | break 262 | } 263 | } 264 | } 265 | 266 | if selected == nil { 267 | for _, man := range mm { 268 | fmt.Println(man.DeviceName, "\t", man.FileName) 269 | } 270 | return 271 | } 272 | fmt.Println("Selected", selected.DeviceName, selected.FileName) 273 | 274 | db, err := backup.Open(selected.FileName) 275 | must(err) 276 | 277 | if db.Manifest.IsEncrypted { 278 | err = db.SetPassword(getpass()) 279 | must(err) 280 | } 281 | must(db.Load()) 282 | if len(os.Args) < 2 { 283 | for _, domain := range db.Domains() { 284 | fmt.Println(domain) 285 | } 286 | return 287 | } 288 | 289 | help := func() { 290 | fmt.Println(`Usage: 291 | ls [domain] 292 | restore domain dest 293 | dumpkeys [outputfile] 294 | apps 295 | `) 296 | } 297 | 298 | var cmd string 299 | if len(os.Args) > 2 { 300 | cmd = os.Args[2] 301 | } 302 | switch cmd { 303 | case "ls", "list": 304 | if len(os.Args) > 3 { 305 | list(db, os.Args[3]) 306 | } else { 307 | domains(db) 308 | } 309 | case "restore": 310 | if len(os.Args) > 4 { 311 | restore(db, os.Args[3], os.Args[4]) 312 | } else { 313 | help() 314 | } 315 | case "apps": 316 | apps(db) 317 | case "dumpkeys": 318 | var out string 319 | if len(os.Args) > 3 { 320 | out = os.Args[3] 321 | } 322 | dumpkeys(db, out) 323 | default: 324 | help() 325 | } 326 | } 327 | -------------------------------------------------------------------------------- /crypto/gcm/gcm.go: -------------------------------------------------------------------------------- 1 | // This package is a modified version of the "gcm" implementation from the cipher package included in go. 2 | // It adds support for Apple's use of null initialization vectors in iOS backup keychains. 3 | 4 | // Copyright 2013 The Go Authors. All rights reserved. 5 | // Use of this source code is governed by a BSD-style 6 | // license that can be found in the LICENSE file. 7 | 8 | package gcm 9 | 10 | import ( 11 | "crypto/cipher" 12 | "crypto/subtle" 13 | "errors" 14 | ) 15 | 16 | // gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM 17 | // standard and make getUint64 suitable for marshaling these values, the bits 18 | // are stored backwards. For example: 19 | // the coefficient of x⁰ can be obtained by v.low >> 63. 20 | // the coefficient of x⁶³ can be obtained by v.low & 1. 21 | // the coefficient of x⁶⁴ can be obtained by v.high >> 63. 22 | // the coefficient of x¹²⁷ can be obtained by v.high & 1. 23 | type gcmFieldElement struct { 24 | low, high uint64 25 | } 26 | 27 | // gcm represents a Galois Counter Mode with a specific key. See 28 | // http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf 29 | type gcm struct { 30 | cipher cipher.Block 31 | // productTable contains the first sixteen powers of the key, H. 32 | // However, they are in bit reversed order. See NewGCM. 33 | productTable [16]gcmFieldElement 34 | } 35 | 36 | // NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode. 37 | func NewGCM(cipher cipher.Block) (cipher.AEAD, error) { 38 | if cipher.BlockSize() != gcmBlockSize { 39 | return nil, errors.New("cipher: NewGCM requires 128-bit block cipher") 40 | } 41 | 42 | var key [gcmBlockSize]byte 43 | cipher.Encrypt(key[:], key[:]) 44 | 45 | g := &gcm{cipher: cipher} 46 | 47 | // We precompute 16 multiples of |key|. However, when we do lookups 48 | // into this table we'll be using bits from a field element and 49 | // therefore the bits will be in the reverse order. So normally one 50 | // would expect, say, 4*key to be in index 4 of the table but due to 51 | // this bit ordering it will actually be in index 0010 (base 2) = 2. 52 | x := gcmFieldElement{ 53 | getUint64(key[:8]), 54 | getUint64(key[8:]), 55 | } 56 | g.productTable[reverseBits(1)] = x 57 | 58 | for i := 2; i < 16; i += 2 { 59 | g.productTable[reverseBits(i)] = gcmDouble(&g.productTable[reverseBits(i/2)]) 60 | g.productTable[reverseBits(i+1)] = gcmAdd(&g.productTable[reverseBits(i)], &x) 61 | } 62 | 63 | return g, nil 64 | } 65 | 66 | const ( 67 | gcmBlockSize = 16 68 | gcmTagSize = 16 69 | gcmNonceSize = 12 70 | ) 71 | 72 | func (*gcm) NonceSize() int { 73 | return gcmNonceSize 74 | } 75 | 76 | func (*gcm) Overhead() int { 77 | return gcmTagSize 78 | } 79 | 80 | func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte { 81 | if len(nonce) != gcmNonceSize { 82 | panic("cipher: incorrect nonce length given to GCM") 83 | } 84 | 85 | ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize) 86 | 87 | // See GCM spec, section 7.1. 88 | var counter, tagMask [gcmBlockSize]byte 89 | copy(counter[:], nonce) 90 | counter[gcmBlockSize-1] = 1 91 | 92 | g.cipher.Encrypt(tagMask[:], counter[:]) 93 | gcmInc32(&counter) 94 | 95 | g.counterCrypt(out, plaintext, &counter) 96 | g.auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask) 97 | 98 | return ret 99 | } 100 | 101 | var errOpen = errors.New("cipher: message authentication failed") 102 | 103 | func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { 104 | 105 | if len(ciphertext) < gcmTagSize { 106 | return nil, errOpen 107 | } 108 | tag := ciphertext[len(ciphertext)-gcmTagSize:] 109 | ciphertext = ciphertext[:len(ciphertext)-gcmTagSize] 110 | 111 | // See GCM spec, section 7.1. 112 | var counter, tagMask [gcmBlockSize]byte 113 | 114 | if len(nonce) != gcmNonceSize { 115 | // counter is all zeros for apple's blank iv 116 | // The python code seems to do the hash inside g.auth for non-12 byte IVs 117 | 118 | } else { 119 | copy(counter[:], nonce) 120 | counter[gcmBlockSize-1] = 1 121 | } 122 | 123 | g.cipher.Encrypt(tagMask[:], counter[:]) 124 | gcmInc32(&counter) 125 | var expectedTag [gcmTagSize]byte 126 | g.auth(expectedTag[:], ciphertext, data, &tagMask) 127 | 128 | if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 { 129 | return nil, errOpen 130 | } 131 | 132 | ret, out := sliceForAppend(dst, len(ciphertext)) 133 | g.counterCrypt(out, ciphertext, &counter) 134 | 135 | return ret, nil 136 | } 137 | 138 | // reverseBits reverses the order of the bits of 4-bit number in i. 139 | func reverseBits(i int) int { 140 | i = ((i << 2) & 0xc) | ((i >> 2) & 0x3) 141 | i = ((i << 1) & 0xa) | ((i >> 1) & 0x5) 142 | return i 143 | } 144 | 145 | // gcmAdd adds two elements of GF(2¹²⁸) and returns the sum. 146 | func gcmAdd(x, y *gcmFieldElement) gcmFieldElement { 147 | // Addition in a characteristic 2 field is just XOR. 148 | return gcmFieldElement{x.low ^ y.low, x.high ^ y.high} 149 | } 150 | 151 | // gcmDouble returns the result of doubling an element of GF(2¹²⁸). 152 | func gcmDouble(x *gcmFieldElement) (double gcmFieldElement) { 153 | msbSet := x.high&1 == 1 154 | 155 | // Because of the bit-ordering, doubling is actually a right shift. 156 | double.high = x.high >> 1 157 | double.high |= x.low << 63 158 | double.low = x.low >> 1 159 | 160 | // If the most-significant bit was set before shifting then it, 161 | // conceptually, becomes a term of x^128. This is greater than the 162 | // irreducible polynomial so the result has to be reduced. The 163 | // irreducible polynomial is 1+x+x^2+x^7+x^128. We can subtract that to 164 | // eliminate the term at x^128 which also means subtracting the other 165 | // four terms. In characteristic 2 fields, subtraction == addition == 166 | // XOR. 167 | if msbSet { 168 | double.low ^= 0xe100000000000000 169 | } 170 | 171 | return 172 | } 173 | 174 | var gcmReductionTable = []uint16{ 175 | 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, 176 | 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0, 177 | } 178 | 179 | // mul sets y to y*H, where H is the GCM key, fixed during NewGCM. 180 | func (g *gcm) mul(y *gcmFieldElement) { 181 | var z gcmFieldElement 182 | 183 | for i := 0; i < 2; i++ { 184 | word := y.high 185 | if i == 1 { 186 | word = y.low 187 | } 188 | 189 | // Multiplication works by multiplying z by 16 and adding in 190 | // one of the precomputed multiples of H. 191 | for j := 0; j < 64; j += 4 { 192 | msw := z.high & 0xf 193 | z.high >>= 4 194 | z.high |= z.low << 60 195 | z.low >>= 4 196 | z.low ^= uint64(gcmReductionTable[msw]) << 48 197 | 198 | // the values in |table| are ordered for 199 | // little-endian bit positions. See the comment 200 | // in NewGCM. 201 | t := &g.productTable[word&0xf] 202 | 203 | z.low ^= t.low 204 | z.high ^= t.high 205 | word >>= 4 206 | } 207 | } 208 | 209 | *y = z 210 | } 211 | 212 | // updateBlocks extends y with more polynomial terms from blocks, based on 213 | // Horner's rule. There must be a multiple of gcmBlockSize bytes in blocks. 214 | func (g *gcm) updateBlocks(y *gcmFieldElement, blocks []byte) { 215 | for len(blocks) > 0 { 216 | y.low ^= getUint64(blocks) 217 | y.high ^= getUint64(blocks[8:]) 218 | g.mul(y) 219 | blocks = blocks[gcmBlockSize:] 220 | } 221 | } 222 | 223 | // update extends y with more polynomial terms from data. If data is not a 224 | // multiple of gcmBlockSize bytes long then the remainder is zero padded. 225 | func (g *gcm) update(y *gcmFieldElement, data []byte) { 226 | fullBlocks := (len(data) >> 4) << 4 227 | g.updateBlocks(y, data[:fullBlocks]) 228 | 229 | if len(data) != fullBlocks { 230 | var partialBlock [gcmBlockSize]byte 231 | copy(partialBlock[:], data[fullBlocks:]) 232 | g.updateBlocks(y, partialBlock[:]) 233 | } 234 | } 235 | 236 | // gcmInc32 treats the final four bytes of counterBlock as a big-endian value 237 | // and increments it. 238 | func gcmInc32(counterBlock *[16]byte) { 239 | for i := gcmBlockSize - 1; i >= gcmBlockSize-4; i-- { 240 | counterBlock[i]++ 241 | if counterBlock[i] != 0 { 242 | break 243 | } 244 | } 245 | } 246 | 247 | // sliceForAppend takes a slice and a requested number of bytes. It returns a 248 | // slice with the contents of the given slice followed by that many bytes and a 249 | // second slice that aliases into it and contains only the extra bytes. If the 250 | // original slice has sufficient capacity then no allocation is performed. 251 | func sliceForAppend(in []byte, n int) (head, tail []byte) { 252 | if total := len(in) + n; cap(in) >= total { 253 | head = in[:total] 254 | } else { 255 | head = make([]byte, total) 256 | copy(head, in) 257 | } 258 | tail = head[len(in):] 259 | return 260 | } 261 | 262 | // counterCrypt crypts in to out using g.cipher in counter mode. 263 | func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) { 264 | var mask [gcmBlockSize]byte 265 | 266 | for len(in) >= gcmBlockSize { 267 | g.cipher.Encrypt(mask[:], counter[:]) 268 | gcmInc32(counter) 269 | 270 | xorWords(out, in, mask[:]) 271 | out = out[gcmBlockSize:] 272 | in = in[gcmBlockSize:] 273 | } 274 | 275 | if len(in) > 0 { 276 | g.cipher.Encrypt(mask[:], counter[:]) 277 | gcmInc32(counter) 278 | xorBytes(out, in, mask[:]) 279 | } 280 | } 281 | 282 | // auth calculates GHASH(ciphertext, additionalData), masks the result with 283 | // tagMask and writes the result to out. 284 | func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) { 285 | var y gcmFieldElement 286 | g.update(&y, additionalData) 287 | g.update(&y, ciphertext) 288 | 289 | y.low ^= uint64(len(additionalData)) * 8 290 | y.high ^= uint64(len(ciphertext)) * 8 291 | 292 | g.mul(&y) 293 | 294 | putUint64(out, y.low) 295 | putUint64(out[8:], y.high) 296 | 297 | xorWords(out, out, tagMask[:]) 298 | } 299 | 300 | func getUint64(data []byte) uint64 { 301 | r := uint64(data[0])<<56 | 302 | uint64(data[1])<<48 | 303 | uint64(data[2])<<40 | 304 | uint64(data[3])<<32 | 305 | uint64(data[4])<<24 | 306 | uint64(data[5])<<16 | 307 | uint64(data[6])<<8 | 308 | uint64(data[7]) 309 | return r 310 | } 311 | 312 | func putUint64(out []byte, v uint64) { 313 | out[0] = byte(v >> 56) 314 | out[1] = byte(v >> 48) 315 | out[2] = byte(v >> 40) 316 | out[3] = byte(v >> 32) 317 | out[4] = byte(v >> 24) 318 | out[5] = byte(v >> 16) 319 | out[6] = byte(v >> 8) 320 | out[7] = byte(v) 321 | } 322 | -------------------------------------------------------------------------------- /backup/backup.go: -------------------------------------------------------------------------------- 1 | // Package backup wraps an iOS backup directory. 2 | package backup 3 | 4 | import ( 5 | "bytes" 6 | "crypto/aes" 7 | "crypto/cipher" 8 | "crypto/sha1" 9 | "database/sql" 10 | "encoding/binary" 11 | "encoding/hex" 12 | "errors" 13 | "fmt" 14 | "io" 15 | "io/ioutil" 16 | "log" 17 | "os" 18 | "path" 19 | "sort" 20 | "runtime" 21 | 22 | "github.com/dunhamsteve/ios/crypto/aeswrap" 23 | "github.com/dunhamsteve/ios/keybag" 24 | "github.com/dunhamsteve/ios/kvarchive" 25 | "github.com/dunhamsteve/plist" 26 | _ "github.com/mattn/go-sqlite3" 27 | ) 28 | 29 | var be = binary.BigEndian 30 | 31 | type MetaData struct { 32 | Mode uint16 33 | Inode uint64 34 | Uid uint32 35 | Gid uint32 36 | Mtime uint32 37 | Atime uint32 38 | Ctime uint32 39 | Length uint64 40 | ProtClass uint8 41 | PropertyCount uint8 42 | } 43 | 44 | type Record struct { 45 | MetaData 46 | Domain string 47 | Path string 48 | LinkTarget string 49 | Digest []byte 50 | Key []byte 51 | Properties map[string][]byte 52 | } 53 | 54 | type DBReader struct { 55 | io.Reader 56 | err error 57 | } 58 | 59 | func (r *Record) HashCode() string { 60 | sum := sha1.Sum([]byte(r.Domain + "-" + r.Path)) 61 | return hex.EncodeToString(sum[:]) 62 | } 63 | 64 | func (r *DBReader) readData() []byte { 65 | var l uint16 66 | r.err = binary.Read(r, be, &l) 67 | if l == 0xffff { 68 | return nil 69 | } 70 | if l > 2048 { 71 | panic(fmt.Sprintf("long name %d", l)) 72 | } 73 | buf := make([]byte, l) 74 | r.Read(buf) 75 | return buf 76 | } 77 | func (r *DBReader) readRecord() Record { 78 | var rec Record 79 | rec.Domain = string(r.readData()) 80 | if r.err != nil { 81 | return rec 82 | } 83 | rec.Path = string(r.readData()) 84 | rec.LinkTarget = string(r.readData()) 85 | rec.Digest = r.readData() 86 | rec.Key = r.readData() 87 | binary.Read(r, be, &rec.MetaData) 88 | rec.Properties = make(map[string][]byte) 89 | for i := uint8(0); i < rec.PropertyCount; i++ { 90 | rec.Properties[string(r.readData())] = r.readData() 91 | } 92 | return rec 93 | } 94 | 95 | func (r *DBReader) readAll() []Record { 96 | var rval []Record 97 | defer func() { 98 | if r := recover(); r != nil { 99 | fmt.Println("Recovered in readAll", r) 100 | } 101 | }() 102 | var header [6]byte 103 | r.Read(header[:]) 104 | for { 105 | rec := r.readRecord() 106 | if r.err != nil { 107 | break 108 | } 109 | rval = append(rval, rec) 110 | } 111 | return rval 112 | } 113 | 114 | // MobileBackup encapsulates a mobile backup manifest 115 | type MobileBackup struct { 116 | Dir string 117 | Manifest Manifest 118 | Records []Record 119 | Keybag keybag.Keybag 120 | 121 | BlobKey []byte 122 | } 123 | 124 | // SetPassword decrypts the keychain. 125 | func (mb *MobileBackup) SetPassword(pass string) error { 126 | return mb.Keybag.SetPassword(pass) 127 | } 128 | 129 | func decrypt(key, data []byte) []byte { 130 | c, err := aes.NewCipher(key) 131 | if err != nil { 132 | log.Panic(err) 133 | } 134 | 135 | var iv [16]byte 136 | for i := range iv { 137 | iv[i] = byte(i) 138 | } 139 | cbc := cipher.NewCBCDecrypter(c, iv[:]) 140 | out := make([]byte, len(data)) 141 | cbc.CryptBlocks(out, data) 142 | 143 | sz := out[len(out)-1] 144 | if sz > 16 || sz < 1 { 145 | log.Fatal("bad pkcs7", sz) 146 | } 147 | end := len(out) - int(sz) 148 | for i := end; i < len(out); i++ { 149 | if out[i] != sz { 150 | log.Fatalln("bad pkcs7", sz) 151 | } 152 | } 153 | // TODO PKCS7 154 | return out[:end] 155 | } 156 | 157 | // FileKey finds the key for a given file record 158 | func (mb *MobileBackup) FileKey(rec Record) []byte { 159 | key := mb.Keybag.GetClassKey(uint32(rec.ProtClass)) 160 | if key != nil { 161 | return aeswrap.Unwrap(key, rec.Key[4:]) 162 | } 163 | log.Println("No key for protection class", rec.ProtClass) 164 | 165 | return nil 166 | } 167 | 168 | var zeroiv = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 169 | 170 | // ReadFile reads the contents of an encrypted file. 171 | func (mb *MobileBackup) ReadFile(rec Record) ([]byte, error) { 172 | key := mb.FileKey(rec) 173 | if key == nil { 174 | return nil, fmt.Errorf("No key for file %v", rec) 175 | } 176 | hcode := rec.HashCode() 177 | fn := path.Join(mb.Dir, hcode) 178 | // New path format 179 | if _, err := os.Stat(fn); err != nil { 180 | fn = path.Join(mb.Dir, hcode[:2], hcode) 181 | } 182 | data, err := ioutil.ReadFile(fn) 183 | if err != nil { 184 | return nil, err 185 | } 186 | b, err := aes.NewCipher(key) 187 | if err != nil { 188 | return nil, err 189 | } 190 | bm := cipher.NewCBCDecrypter(b, zeroiv) 191 | bm.CryptBlocks(data, data) 192 | 193 | return unpad(data), nil 194 | } 195 | 196 | // unpad removes pkcs7 padding, returns nil if invalid. 197 | func unpad(data []byte) []byte { 198 | l := len(data) 199 | c := data[l-1] 200 | if c > 16 { 201 | return nil 202 | } 203 | for i := 0; i < int(c); i++ { 204 | if data[l-i-1] != c { 205 | return nil 206 | } 207 | } 208 | return data[:l-int(c)] 209 | } 210 | 211 | // Domains lists the file domains in a backup manifest. 212 | func (mb *MobileBackup) Domains() []string { 213 | domains := make(map[string]bool) 214 | for _, rec := range mb.Records { 215 | domains[rec.Domain] = true 216 | } 217 | rval := make([]string, 0, len(domains)) 218 | for k := range domains { 219 | rval = append(rval, k) 220 | } 221 | sort.Strings(rval) 222 | return rval 223 | } 224 | 225 | // FileReader returns an io.Reader for the unencrypted contents of a file record 226 | func (mb *MobileBackup) FileReader(rec Record) (io.ReadCloser, error) { 227 | rval := new(reader) 228 | key := mb.FileKey(rec) 229 | 230 | if key == nil { 231 | return nil, errors.New("Can't get key for " + rec.Domain + "-" + rec.Path) 232 | } 233 | hcode := rec.HashCode() 234 | fn := path.Join(mb.Dir, hcode) 235 | // New path format 236 | if _, err := os.Stat(fn); err != nil { 237 | fn = path.Join(mb.Dir, hcode[:2], hcode) 238 | } 239 | rval.r, rval.err = os.Open(fn) 240 | if rval.err != nil { 241 | return nil, rval.err 242 | } 243 | 244 | b, err := aes.NewCipher(key) 245 | if err != nil { 246 | return nil, err 247 | } 248 | 249 | cipher := cipher.NewCBCDecrypter(b, zeroiv) 250 | rval.ch = make(chan []byte) 251 | // Feeds 4k blocks to the channel until we run out of file. 252 | // Handles padding on last block and EOF detection by holding 16 bytes in reserve. 253 | go func() { 254 | var n int 255 | prev := make([]byte, 16) 256 | n, rval.err = io.ReadFull(rval.r, prev) 257 | if n != 16 { 258 | rval.err = errors.New("short read of IV") 259 | rval.ch <- nil 260 | return 261 | } 262 | cipher.CryptBlocks(prev, prev) 263 | for { 264 | var n int 265 | buf := make([]byte, 4096+16) 266 | copy(buf, prev) 267 | n, rval.err = io.ReadFull(rval.r, buf[16:]) 268 | if rval.err == io.ErrUnexpectedEOF { 269 | rval.err = io.EOF 270 | } 271 | if rval.err == nil && n != 4096 { 272 | panic("Unexpected read size") 273 | } 274 | cipher.CryptBlocks(buf[16:], buf[16:]) 275 | if rval.err == io.EOF { 276 | buf = buf[:16+n] 277 | buf = unpad(buf) 278 | if buf == nil { 279 | rval.err = errors.New("Bad Padding") 280 | } 281 | rval.ch <- buf 282 | rval.ch <- nil 283 | return 284 | } 285 | rval.ch <- buf[:n] 286 | copy(prev, buf[n:]) 287 | 288 | if rval.err != nil { 289 | fmt.Println(" other error", rval.err) 290 | rval.ch <- nil 291 | return 292 | } 293 | } 294 | }() 295 | rval.buf = <-rval.ch 296 | return rval, rval.err 297 | } 298 | 299 | // CBC+PKCS7 reader 300 | type reader struct { 301 | r io.ReadCloser 302 | ch chan []byte 303 | cipher cipher.BlockMode 304 | buf []byte 305 | pos uint32 306 | err error 307 | } 308 | 309 | func min(a int, b int) int { 310 | if a < b { 311 | return a 312 | } 313 | return b 314 | } 315 | 316 | func (r *reader) Read(p []byte) (n int, err error) { 317 | want := len(p) 318 | for { 319 | if want == 0 { 320 | return 321 | } 322 | if len(r.buf) == 0 { 323 | r.buf = <-r.ch 324 | if r.buf == nil { 325 | return n, r.err 326 | } 327 | } 328 | i := min(want, len(r.buf)) 329 | copy(p, r.buf[:i]) 330 | r.buf = r.buf[i:] 331 | p = p[i:] 332 | want -= i 333 | n += i 334 | } 335 | } 336 | 337 | func (r *reader) Close() error { 338 | return r.r.Close() 339 | } 340 | 341 | type Manifest struct { 342 | BackupKeyBag []byte 343 | Lockdown struct { 344 | DeviceName string 345 | } 346 | Applications map[string]map[string]interface{} 347 | IsEncrypted bool 348 | ManifestKey []byte // this is wrapped 349 | } 350 | 351 | type Backup struct { 352 | DeviceName string 353 | FileName string 354 | } 355 | 356 | // Enumerate lists the available backups 357 | func Enumerate() ([]Backup, error) { 358 | var all []Backup 359 | var home string 360 | var dir string 361 | if runtime.GOOS == "windows" { 362 | home = os.Getenv("APPDATA") 363 | dir = path.Join(home, "Apple Computer\\MobileSync\\Backup") 364 | } else { 365 | home = os.Getenv("HOME") 366 | dir = path.Join(home, "Library/Application Support/MobileSync/Backup") 367 | } 368 | r, err := os.Open(dir) 369 | if err != nil { 370 | return nil, err 371 | } 372 | infos, err := r.Readdir(-1) 373 | if err != nil { 374 | return nil, err 375 | } 376 | for _, fi := range infos { 377 | if fi.IsDir() { 378 | pl := path.Join(dir, fi.Name(), "Manifest.plist") 379 | if r, err := os.Open(pl); err == nil { 380 | defer r.Close() 381 | var manifest Manifest 382 | err = plist.Unmarshal(r, &manifest) 383 | if err == nil { 384 | all = append(all, Backup{manifest.Lockdown.DeviceName, fi.Name()}) 385 | } 386 | } 387 | } 388 | } 389 | 390 | return all, nil 391 | } 392 | 393 | // Open opens a MobileBackup directory corresponding to a given guid. 394 | func Open(guid string) (*MobileBackup, error) { 395 | var backup MobileBackup 396 | var home string 397 | if runtime.GOOS == "windows" { 398 | home = os.Getenv("APPDATA") 399 | backup.Dir = path.Join(home, "Apple Computer\\MobileSync\\Backup", guid) 400 | } else { 401 | home = os.Getenv("HOME") 402 | backup.Dir = path.Join(home, "Library/Application Support/MobileSync/Backup", guid) 403 | } 404 | 405 | tmp := path.Join(backup.Dir, "Manifest.plist") 406 | r, err := os.Open(tmp) 407 | if err != nil { 408 | return nil, err 409 | } 410 | defer r.Close() 411 | err = plist.Unmarshal(r, &backup.Manifest) 412 | if err != nil { 413 | return nil, err 414 | } 415 | backup.Keybag = keybag.Read(backup.Manifest.BackupKeyBag) 416 | return &backup, nil 417 | } 418 | 419 | // Load loads the backup. It must be called after "SetPassword" for 420 | // ios 10.2+ encrypted backups, and must be called before attempting 421 | // to use any other methods on MobileBackup. 422 | func (mb *MobileBackup) Load() error { 423 | // Try to read old Manifest 424 | err := mb.readOldManifest() 425 | if err == nil { 426 | return nil 427 | } 428 | 429 | // try to read new manifest 430 | return mb.readNewManifest() 431 | } 432 | 433 | func (mb *MobileBackup) decryptDatabase(fn string, mk []byte) (string, error) { 434 | var err error 435 | class := binary.LittleEndian.Uint32(mk) 436 | ckey := mb.Keybag.GetClassKey(class) 437 | if ckey == nil { 438 | return "", fmt.Errorf("No manifest key for class %d", class) 439 | } 440 | key := aeswrap.Unwrap(ckey, mk[4:]) 441 | fmt.Println("Got manifest key", key) 442 | data, err := ioutil.ReadFile(fn) 443 | if err != nil { 444 | return "", err 445 | } 446 | b, err := aes.NewCipher(key) 447 | if err != nil { 448 | return "", err 449 | } 450 | bm := cipher.NewCBCDecrypter(b, zeroiv) 451 | bm.CryptBlocks(data, data) 452 | out, err := ioutil.TempFile("", "db") 453 | if err != nil { 454 | return "", err 455 | } 456 | out.Write(data) 457 | out.Close() 458 | return out.Name(), nil 459 | } 460 | 461 | func (mb *MobileBackup) readNewManifest() error { 462 | var err error 463 | fmt.Println("load") 464 | tmp := path.Join(mb.Dir, "Manifest.db") 465 | mk := mb.Manifest.ManifestKey 466 | 467 | if mk != nil { 468 | tmp, err = mb.decryptDatabase(tmp, mk) 469 | if err != nil { 470 | return err 471 | } 472 | defer os.Remove(tmp) 473 | } 474 | 475 | db, err := sql.Open("sqlite3", tmp) 476 | if err != nil { 477 | return err 478 | } 479 | rows, err := db.Query("select * from files") 480 | if err != nil { 481 | return err 482 | } 483 | for rows.Next() { 484 | var id, domain, path *string 485 | var data []byte 486 | var flags int 487 | var record Record 488 | 489 | err = rows.Scan(&id, &domain, &path, &flags, &data) 490 | if err != nil { 491 | return err 492 | } 493 | // Not sure if this happens anymore 494 | if domain == nil { 495 | continue 496 | } 497 | 498 | record.Domain = *domain 499 | 500 | tmp, err := kvarchive.UnArchive(bytes.NewReader(data)) 501 | if err != nil { 502 | panic(err) 503 | } 504 | frec := tmp.(map[string]interface{}) 505 | // TODO - teach kvarchive to read into structures. 506 | record.Key, _ = frec["EncryptionKey"].([]byte) 507 | record.ProtClass = uint8(frec["ProtectionClass"].(int64)) 508 | record.Length = uint64(frec["Size"].(int64)) 509 | record.Mode = uint16(frec["Mode"].(int64)) 510 | record.Gid = uint32(frec["GroupID"].(int64)) 511 | record.Uid = uint32(frec["UserID"].(int64)) 512 | record.Ctime = uint32(frec["Birth"].(int64)) 513 | record.Atime = uint32(frec["LastModified"].(int64)) 514 | record.Path = frec["RelativePath"].(string) 515 | 516 | mb.Records = append(mb.Records, record) 517 | } 518 | 519 | return nil 520 | } 521 | 522 | func (mb *MobileBackup) readOldManifest() error { 523 | tmp := path.Join(mb.Dir, "Manifest.mbdb") 524 | r2, err := os.Open(tmp) 525 | if err == nil { 526 | var dbr DBReader 527 | dbr.Reader = r2 528 | defer r2.Close() 529 | mb.Records = dbr.readAll() 530 | return nil 531 | } 532 | return err 533 | } 534 | -------------------------------------------------------------------------------- /encoding/asn1/marshal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 asn1 6 | 7 | import ( 8 | "bytes" 9 | "errors" 10 | "fmt" 11 | "io" 12 | "math/big" 13 | "reflect" 14 | "time" 15 | "unicode/utf8" 16 | ) 17 | 18 | // A forkableWriter is an in-memory buffer that can be 19 | // 'forked' to create new forkableWriters that bracket the 20 | // original. After 21 | // pre, post := w.fork() 22 | // the overall sequence of bytes represented is logically w+pre+post. 23 | type forkableWriter struct { 24 | *bytes.Buffer 25 | pre, post *forkableWriter 26 | } 27 | 28 | func newForkableWriter() *forkableWriter { 29 | return &forkableWriter{new(bytes.Buffer), nil, nil} 30 | } 31 | 32 | func (f *forkableWriter) fork() (pre, post *forkableWriter) { 33 | if f.pre != nil || f.post != nil { 34 | panic("have already forked") 35 | } 36 | f.pre = newForkableWriter() 37 | f.post = newForkableWriter() 38 | return f.pre, f.post 39 | } 40 | 41 | func (f *forkableWriter) Len() (l int) { 42 | l += f.Buffer.Len() 43 | if f.pre != nil { 44 | l += f.pre.Len() 45 | } 46 | if f.post != nil { 47 | l += f.post.Len() 48 | } 49 | return 50 | } 51 | 52 | func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) { 53 | n, err = out.Write(f.Bytes()) 54 | if err != nil { 55 | return 56 | } 57 | 58 | var nn int 59 | 60 | if f.pre != nil { 61 | nn, err = f.pre.writeTo(out) 62 | n += nn 63 | if err != nil { 64 | return 65 | } 66 | } 67 | 68 | if f.post != nil { 69 | nn, err = f.post.writeTo(out) 70 | n += nn 71 | } 72 | return 73 | } 74 | 75 | func marshalBase128Int(out *forkableWriter, n int64) (err error) { 76 | if n == 0 { 77 | err = out.WriteByte(0) 78 | return 79 | } 80 | 81 | l := 0 82 | for i := n; i > 0; i >>= 7 { 83 | l++ 84 | } 85 | 86 | for i := l - 1; i >= 0; i-- { 87 | o := byte(n >> uint(i*7)) 88 | o &= 0x7f 89 | if i != 0 { 90 | o |= 0x80 91 | } 92 | err = out.WriteByte(o) 93 | if err != nil { 94 | return 95 | } 96 | } 97 | 98 | return nil 99 | } 100 | 101 | func marshalInt64(out *forkableWriter, i int64) (err error) { 102 | n := int64Length(i) 103 | 104 | for ; n > 0; n-- { 105 | err = out.WriteByte(byte(i >> uint((n-1)*8))) 106 | if err != nil { 107 | return 108 | } 109 | } 110 | 111 | return nil 112 | } 113 | 114 | func int64Length(i int64) (numBytes int) { 115 | numBytes = 1 116 | 117 | for i > 127 { 118 | numBytes++ 119 | i >>= 8 120 | } 121 | 122 | for i < -128 { 123 | numBytes++ 124 | i >>= 8 125 | } 126 | 127 | return 128 | } 129 | 130 | func marshalBigInt(out *forkableWriter, n *big.Int) (err error) { 131 | if n.Sign() < 0 { 132 | // A negative number has to be converted to two's-complement 133 | // form. So we'll subtract 1 and invert. If the 134 | // most-significant-bit isn't set then we'll need to pad the 135 | // beginning with 0xff in order to keep the number negative. 136 | nMinus1 := new(big.Int).Neg(n) 137 | nMinus1.Sub(nMinus1, bigOne) 138 | bytes := nMinus1.Bytes() 139 | for i := range bytes { 140 | bytes[i] ^= 0xff 141 | } 142 | if len(bytes) == 0 || bytes[0]&0x80 == 0 { 143 | err = out.WriteByte(0xff) 144 | if err != nil { 145 | return 146 | } 147 | } 148 | _, err = out.Write(bytes) 149 | } else if n.Sign() == 0 { 150 | // Zero is written as a single 0 zero rather than no bytes. 151 | err = out.WriteByte(0x00) 152 | } else { 153 | bytes := n.Bytes() 154 | if len(bytes) > 0 && bytes[0]&0x80 != 0 { 155 | // We'll have to pad this with 0x00 in order to stop it 156 | // looking like a negative number. 157 | err = out.WriteByte(0) 158 | if err != nil { 159 | return 160 | } 161 | } 162 | _, err = out.Write(bytes) 163 | } 164 | return 165 | } 166 | 167 | func marshalLength(out *forkableWriter, i int) (err error) { 168 | n := lengthLength(i) 169 | 170 | for ; n > 0; n-- { 171 | err = out.WriteByte(byte(i >> uint((n-1)*8))) 172 | if err != nil { 173 | return 174 | } 175 | } 176 | 177 | return nil 178 | } 179 | 180 | func lengthLength(i int) (numBytes int) { 181 | numBytes = 1 182 | for i > 255 { 183 | numBytes++ 184 | i >>= 8 185 | } 186 | return 187 | } 188 | 189 | func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) { 190 | b := uint8(t.class) << 6 191 | if t.isCompound { 192 | b |= 0x20 193 | } 194 | if t.tag >= 31 { 195 | b |= 0x1f 196 | err = out.WriteByte(b) 197 | if err != nil { 198 | return 199 | } 200 | err = marshalBase128Int(out, int64(t.tag)) 201 | if err != nil { 202 | return 203 | } 204 | } else { 205 | b |= uint8(t.tag) 206 | err = out.WriteByte(b) 207 | if err != nil { 208 | return 209 | } 210 | } 211 | 212 | if t.length >= 128 { 213 | l := lengthLength(t.length) 214 | err = out.WriteByte(0x80 | byte(l)) 215 | if err != nil { 216 | return 217 | } 218 | err = marshalLength(out, t.length) 219 | if err != nil { 220 | return 221 | } 222 | } else { 223 | err = out.WriteByte(byte(t.length)) 224 | if err != nil { 225 | return 226 | } 227 | } 228 | 229 | return nil 230 | } 231 | 232 | func marshalBitString(out *forkableWriter, b BitString) (err error) { 233 | paddingBits := byte((8 - b.BitLength%8) % 8) 234 | err = out.WriteByte(paddingBits) 235 | if err != nil { 236 | return 237 | } 238 | _, err = out.Write(b.Bytes) 239 | return 240 | } 241 | 242 | func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) { 243 | if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) { 244 | return StructuralError{"invalid object identifier"} 245 | } 246 | 247 | err = marshalBase128Int(out, int64(oid[0]*40+oid[1])) 248 | if err != nil { 249 | return 250 | } 251 | for i := 2; i < len(oid); i++ { 252 | err = marshalBase128Int(out, int64(oid[i])) 253 | if err != nil { 254 | return 255 | } 256 | } 257 | 258 | return 259 | } 260 | 261 | func marshalPrintableString(out *forkableWriter, s string) (err error) { 262 | b := []byte(s) 263 | for _, c := range b { 264 | if !isPrintable(c) { 265 | return StructuralError{"PrintableString contains invalid character"} 266 | } 267 | } 268 | 269 | _, err = out.Write(b) 270 | return 271 | } 272 | 273 | func marshalIA5String(out *forkableWriter, s string) (err error) { 274 | b := []byte(s) 275 | for _, c := range b { 276 | if c > 127 { 277 | return StructuralError{"IA5String contains invalid character"} 278 | } 279 | } 280 | 281 | _, err = out.Write(b) 282 | return 283 | } 284 | 285 | func marshalUTF8String(out *forkableWriter, s string) (err error) { 286 | _, err = out.Write([]byte(s)) 287 | return 288 | } 289 | 290 | func marshalTwoDigits(out *forkableWriter, v int) (err error) { 291 | err = out.WriteByte(byte('0' + (v/10)%10)) 292 | if err != nil { 293 | return 294 | } 295 | return out.WriteByte(byte('0' + v%10)) 296 | } 297 | 298 | func marshalFourDigits(out *forkableWriter, v int) (err error) { 299 | var bytes [4]byte 300 | for i := range bytes { 301 | bytes[3-i] = '0' + byte(v%10) 302 | v /= 10 303 | } 304 | _, err = out.Write(bytes[:]) 305 | return 306 | } 307 | 308 | func outsideUTCRange(t time.Time) bool { 309 | year := t.Year() 310 | return year < 1950 || year >= 2050 311 | } 312 | 313 | func marshalUTCTime(out *forkableWriter, t time.Time) (err error) { 314 | year := t.Year() 315 | 316 | switch { 317 | case 1950 <= year && year < 2000: 318 | err = marshalTwoDigits(out, int(year-1900)) 319 | case 2000 <= year && year < 2050: 320 | err = marshalTwoDigits(out, int(year-2000)) 321 | default: 322 | return StructuralError{"cannot represent time as UTCTime"} 323 | } 324 | if err != nil { 325 | return 326 | } 327 | 328 | return marshalTimeCommon(out, t) 329 | } 330 | 331 | func marshalGeneralizedTime(out *forkableWriter, t time.Time) (err error) { 332 | year := t.Year() 333 | if year < 0 || year > 9999 { 334 | return StructuralError{"cannot represent time as GeneralizedTime"} 335 | } 336 | if err = marshalFourDigits(out, year); err != nil { 337 | return 338 | } 339 | 340 | return marshalTimeCommon(out, t) 341 | } 342 | 343 | func marshalTimeCommon(out *forkableWriter, t time.Time) (err error) { 344 | _, month, day := t.Date() 345 | 346 | err = marshalTwoDigits(out, int(month)) 347 | if err != nil { 348 | return 349 | } 350 | 351 | err = marshalTwoDigits(out, day) 352 | if err != nil { 353 | return 354 | } 355 | 356 | hour, min, sec := t.Clock() 357 | 358 | err = marshalTwoDigits(out, hour) 359 | if err != nil { 360 | return 361 | } 362 | 363 | err = marshalTwoDigits(out, min) 364 | if err != nil { 365 | return 366 | } 367 | 368 | err = marshalTwoDigits(out, sec) 369 | if err != nil { 370 | return 371 | } 372 | 373 | _, offset := t.Zone() 374 | 375 | switch { 376 | case offset/60 == 0: 377 | err = out.WriteByte('Z') 378 | return 379 | case offset > 0: 380 | err = out.WriteByte('+') 381 | case offset < 0: 382 | err = out.WriteByte('-') 383 | } 384 | 385 | if err != nil { 386 | return 387 | } 388 | 389 | offsetMinutes := offset / 60 390 | if offsetMinutes < 0 { 391 | offsetMinutes = -offsetMinutes 392 | } 393 | 394 | err = marshalTwoDigits(out, offsetMinutes/60) 395 | if err != nil { 396 | return 397 | } 398 | 399 | err = marshalTwoDigits(out, offsetMinutes%60) 400 | return 401 | } 402 | 403 | func stripTagAndLength(in []byte) []byte { 404 | _, offset, err := parseTagAndLength(in, 0) 405 | if err != nil { 406 | return in 407 | } 408 | return in[offset:] 409 | } 410 | 411 | func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) { 412 | switch value.Type() { 413 | case flagType: 414 | return nil 415 | case timeType: 416 | t := value.Interface().(time.Time) 417 | if params.timeType == TagGeneralizedTime || outsideUTCRange(t) { 418 | return marshalGeneralizedTime(out, t) 419 | } else { 420 | return marshalUTCTime(out, t) 421 | } 422 | case bitStringType: 423 | return marshalBitString(out, value.Interface().(BitString)) 424 | case objectIdentifierType: 425 | return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier)) 426 | case bigIntType: 427 | return marshalBigInt(out, value.Interface().(*big.Int)) 428 | } 429 | 430 | switch v := value; v.Kind() { 431 | case reflect.Bool: 432 | if v.Bool() { 433 | return out.WriteByte(255) 434 | } else { 435 | return out.WriteByte(0) 436 | } 437 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 438 | return marshalInt64(out, int64(v.Int())) 439 | case reflect.Struct: 440 | t := v.Type() 441 | 442 | startingField := 0 443 | 444 | // If the first element of the structure is a non-empty 445 | // RawContents, then we don't bother serializing the rest. 446 | if t.NumField() > 0 && t.Field(0).Type == rawContentsType { 447 | s := v.Field(0) 448 | if s.Len() > 0 { 449 | bytes := make([]byte, s.Len()) 450 | for i := 0; i < s.Len(); i++ { 451 | bytes[i] = uint8(s.Index(i).Uint()) 452 | } 453 | /* The RawContents will contain the tag and 454 | * length fields but we'll also be writing 455 | * those ourselves, so we strip them out of 456 | * bytes */ 457 | _, err = out.Write(stripTagAndLength(bytes)) 458 | return 459 | } else { 460 | startingField = 1 461 | } 462 | } 463 | 464 | for i := startingField; i < t.NumField(); i++ { 465 | var pre *forkableWriter 466 | pre, out = out.fork() 467 | err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1"))) 468 | if err != nil { 469 | return 470 | } 471 | } 472 | return 473 | case reflect.Slice: 474 | sliceType := v.Type() 475 | if sliceType.Elem().Kind() == reflect.Uint8 { 476 | bytes := make([]byte, v.Len()) 477 | for i := 0; i < v.Len(); i++ { 478 | bytes[i] = uint8(v.Index(i).Uint()) 479 | } 480 | _, err = out.Write(bytes) 481 | return 482 | } 483 | 484 | var fp fieldParameters 485 | for i := 0; i < v.Len(); i++ { 486 | var pre *forkableWriter 487 | pre, out = out.fork() 488 | err = marshalField(pre, v.Index(i), fp) 489 | if err != nil { 490 | return 491 | } 492 | } 493 | return 494 | case reflect.String: 495 | switch params.stringType { 496 | case TagIA5String: 497 | return marshalIA5String(out, v.String()) 498 | case TagPrintableString: 499 | return marshalPrintableString(out, v.String()) 500 | default: 501 | return marshalUTF8String(out, v.String()) 502 | } 503 | } 504 | 505 | return StructuralError{"unknown Go type"} 506 | } 507 | 508 | func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) { 509 | if !v.IsValid() { 510 | return fmt.Errorf("asn1: cannot marshal nil value") 511 | } 512 | // If the field is an interface{} then recurse into it. 513 | if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { 514 | return marshalField(out, v.Elem(), params) 515 | } 516 | 517 | if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty { 518 | return 519 | } 520 | 521 | if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) { 522 | defaultValue := reflect.New(v.Type()).Elem() 523 | defaultValue.SetInt(*params.defaultValue) 524 | 525 | if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) { 526 | return 527 | } 528 | } 529 | 530 | // If no default value is given then the zero value for the type is 531 | // assumed to be the default value. This isn't obviously the correct 532 | // behaviour, but it's what Go has traditionally done. 533 | if params.optional && params.defaultValue == nil { 534 | if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { 535 | return 536 | } 537 | } 538 | 539 | if v.Type() == rawValueType { 540 | rv := v.Interface().(RawValue) 541 | if len(rv.FullBytes) != 0 { 542 | _, err = out.Write(rv.FullBytes) 543 | } else { 544 | err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}) 545 | if err != nil { 546 | return 547 | } 548 | _, err = out.Write(rv.Bytes) 549 | } 550 | return 551 | } 552 | 553 | tag, isCompound, ok := getUniversalType(v.Type()) 554 | if !ok { 555 | err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())} 556 | return 557 | } 558 | class := ClassUniversal 559 | 560 | if params.timeType != 0 && tag != TagUTCTime { 561 | return StructuralError{"explicit time type given to non-time member"} 562 | } 563 | 564 | if params.stringType != 0 && tag != TagPrintableString { 565 | return StructuralError{"explicit string type given to non-string member"} 566 | } 567 | 568 | switch tag { 569 | case TagPrintableString: 570 | if params.stringType == 0 { 571 | // This is a string without an explicit string type. We'll use 572 | // a PrintableString if the character set in the string is 573 | // sufficiently limited, otherwise we'll use a UTF8String. 574 | for _, r := range v.String() { 575 | if r >= utf8.RuneSelf || !isPrintable(byte(r)) { 576 | if !utf8.ValidString(v.String()) { 577 | return errors.New("asn1: string not valid UTF-8") 578 | } 579 | tag = TagUTF8String 580 | break 581 | } 582 | } 583 | } else { 584 | tag = params.stringType 585 | } 586 | case TagUTCTime: 587 | if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) { 588 | tag = TagGeneralizedTime 589 | } 590 | } 591 | 592 | if params.set { 593 | if tag != TagSequence { 594 | return StructuralError{"non sequence tagged as set"} 595 | } 596 | tag = TagSet 597 | } 598 | 599 | tags, body := out.fork() 600 | 601 | err = marshalBody(body, v, params) 602 | if err != nil { 603 | return 604 | } 605 | 606 | bodyLen := body.Len() 607 | 608 | var explicitTag *forkableWriter 609 | if params.explicit { 610 | explicitTag, tags = tags.fork() 611 | } 612 | 613 | if !params.explicit && params.tag != nil { 614 | // implicit tag. 615 | tag = *params.tag 616 | class = ClassContextSpecific 617 | } 618 | 619 | err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound}) 620 | if err != nil { 621 | return 622 | } 623 | 624 | if params.explicit { 625 | err = marshalTagAndLength(explicitTag, tagAndLength{ 626 | class: ClassContextSpecific, 627 | tag: *params.tag, 628 | length: bodyLen + tags.Len(), 629 | isCompound: true, 630 | }) 631 | } 632 | 633 | return err 634 | } 635 | 636 | // Marshal returns the ASN.1 encoding of val. 637 | // 638 | // In addition to the struct tags recognised by Unmarshal, the following can be 639 | // used: 640 | // 641 | // ia5: causes strings to be marshaled as ASN.1, IA5 strings 642 | // omitempty: causes empty slices to be skipped 643 | // printable: causes strings to be marshaled as ASN.1, PrintableString strings. 644 | // utf8: causes strings to be marshaled as ASN.1, UTF8 strings 645 | func Marshal(val interface{}) ([]byte, error) { 646 | var out bytes.Buffer 647 | v := reflect.ValueOf(val) 648 | f := newForkableWriter() 649 | err := marshalField(f, v, fieldParameters{}) 650 | if err != nil { 651 | return nil, err 652 | } 653 | _, err = f.writeTo(&out) 654 | return out.Bytes(), err 655 | } 656 | -------------------------------------------------------------------------------- /encoding/asn1/asn1.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 asn1 implements parsing of DER-encoded ASN.1 data structures, 6 | // as defined in ITU-T Rec X.690. 7 | // 8 | // See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,'' 9 | // http://luca.ntop.org/Teaching/Appunti/asn1.html. 10 | package asn1 11 | 12 | // ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc 13 | // are different encoding formats for those objects. Here, we'll be dealing 14 | // with DER, the Distinguished Encoding Rules. DER is used in X.509 because 15 | // it's fast to parse and, unlike BER, has a unique encoding for every object. 16 | // When calculating hashes over objects, it's important that the resulting 17 | // bytes be the same at both ends and DER removes this margin of error. 18 | // 19 | // ASN.1 is very complex and this package doesn't attempt to implement 20 | // everything by any means. 21 | 22 | import ( 23 | "errors" 24 | "fmt" 25 | "math/big" 26 | "reflect" 27 | "strconv" 28 | "time" 29 | "unicode/utf8" 30 | ) 31 | 32 | // A StructuralError suggests that the ASN.1 data is valid, but the Go type 33 | // which is receiving it doesn't match. 34 | type StructuralError struct { 35 | Msg string 36 | } 37 | 38 | func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg } 39 | 40 | // A SyntaxError suggests that the ASN.1 data is invalid. 41 | type SyntaxError struct { 42 | Msg string 43 | } 44 | 45 | func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg } 46 | 47 | // We start by dealing with each of the primitive types in turn. 48 | 49 | // BOOLEAN 50 | 51 | func parseBool(bytes []byte) (ret bool, err error) { 52 | if len(bytes) != 1 { 53 | err = SyntaxError{"invalid boolean"} 54 | return 55 | } 56 | 57 | // DER demands that "If the encoding represents the boolean value TRUE, 58 | // its single contents octet shall have all eight bits set to one." 59 | // Thus only 0 and 255 are valid encoded values. 60 | switch bytes[0] { 61 | case 0: 62 | ret = false 63 | case 0xff: 64 | ret = true 65 | default: 66 | err = SyntaxError{"invalid boolean"} 67 | } 68 | 69 | return 70 | } 71 | 72 | // INTEGER 73 | 74 | // checkInteger returns nil if the given bytes are a valid DER-encoded 75 | // INTEGER and an error otherwise. 76 | func checkInteger(bytes []byte) error { 77 | if len(bytes) == 0 { 78 | return StructuralError{"empty integer"} 79 | } 80 | if len(bytes) == 1 { 81 | return nil 82 | } 83 | if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) { 84 | return StructuralError{"integer not minimally-encoded"} 85 | } 86 | return nil 87 | } 88 | 89 | // parseInt64 treats the given bytes as a big-endian, signed integer and 90 | // returns the result. 91 | func parseInt64(bytes []byte) (ret int64, err error) { 92 | err = checkInteger(bytes) 93 | if err != nil { 94 | return 95 | } 96 | if len(bytes) > 8 { 97 | // We'll overflow an int64 in this case. 98 | err = StructuralError{"integer too large"} 99 | return 100 | } 101 | for bytesRead := 0; bytesRead < len(bytes); bytesRead++ { 102 | ret <<= 8 103 | ret |= int64(bytes[bytesRead]) 104 | } 105 | 106 | // Shift up and down in order to sign extend the result. 107 | ret <<= 64 - uint8(len(bytes))*8 108 | ret >>= 64 - uint8(len(bytes))*8 109 | return 110 | } 111 | 112 | // parseInt treats the given bytes as a big-endian, signed integer and returns 113 | // the result. 114 | func parseInt32(bytes []byte) (int32, error) { 115 | if err := checkInteger(bytes); err != nil { 116 | return 0, err 117 | } 118 | ret64, err := parseInt64(bytes) 119 | if err != nil { 120 | return 0, err 121 | } 122 | if ret64 != int64(int32(ret64)) { 123 | return 0, StructuralError{"integer too large"} 124 | } 125 | return int32(ret64), nil 126 | } 127 | 128 | var bigOne = big.NewInt(1) 129 | 130 | // parseBigInt treats the given bytes as a big-endian, signed integer and returns 131 | // the result. 132 | func parseBigInt(bytes []byte) (*big.Int, error) { 133 | if err := checkInteger(bytes); err != nil { 134 | return nil, err 135 | } 136 | ret := new(big.Int) 137 | if len(bytes) > 0 && bytes[0]&0x80 == 0x80 { 138 | // This is a negative number. 139 | notBytes := make([]byte, len(bytes)) 140 | for i := range notBytes { 141 | notBytes[i] = ^bytes[i] 142 | } 143 | ret.SetBytes(notBytes) 144 | ret.Add(ret, bigOne) 145 | ret.Neg(ret) 146 | return ret, nil 147 | } 148 | ret.SetBytes(bytes) 149 | return ret, nil 150 | } 151 | 152 | // BIT STRING 153 | 154 | // BitString is the structure to use when you want an ASN.1 BIT STRING type. A 155 | // bit string is padded up to the nearest byte in memory and the number of 156 | // valid bits is recorded. Padding bits will be zero. 157 | type BitString struct { 158 | Bytes []byte // bits packed into bytes. 159 | BitLength int // length in bits. 160 | } 161 | 162 | // At returns the bit at the given index. If the index is out of range it 163 | // returns false. 164 | func (b BitString) At(i int) int { 165 | if i < 0 || i >= b.BitLength { 166 | return 0 167 | } 168 | x := i / 8 169 | y := 7 - uint(i%8) 170 | return int(b.Bytes[x]>>y) & 1 171 | } 172 | 173 | // RightAlign returns a slice where the padding bits are at the beginning. The 174 | // slice may share memory with the BitString. 175 | func (b BitString) RightAlign() []byte { 176 | shift := uint(8 - (b.BitLength % 8)) 177 | if shift == 8 || len(b.Bytes) == 0 { 178 | return b.Bytes 179 | } 180 | 181 | a := make([]byte, len(b.Bytes)) 182 | a[0] = b.Bytes[0] >> shift 183 | for i := 1; i < len(b.Bytes); i++ { 184 | a[i] = b.Bytes[i-1] << (8 - shift) 185 | a[i] |= b.Bytes[i] >> shift 186 | } 187 | 188 | return a 189 | } 190 | 191 | // parseBitString parses an ASN.1 bit string from the given byte slice and returns it. 192 | func parseBitString(bytes []byte) (ret BitString, err error) { 193 | if len(bytes) == 0 { 194 | err = SyntaxError{"zero length BIT STRING"} 195 | return 196 | } 197 | paddingBits := int(bytes[0]) 198 | if paddingBits > 7 || 199 | len(bytes) == 1 && paddingBits > 0 || 200 | bytes[len(bytes)-1]&((1< 0 { 233 | s += "." 234 | } 235 | s += strconv.Itoa(v) 236 | } 237 | 238 | return s 239 | } 240 | 241 | // parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and 242 | // returns it. An object identifier is a sequence of variable length integers 243 | // that are assigned in a hierarchy. 244 | func parseObjectIdentifier(bytes []byte) (s []int, err error) { 245 | if len(bytes) == 0 { 246 | err = SyntaxError{"zero length OBJECT IDENTIFIER"} 247 | return 248 | } 249 | 250 | // In the worst case, we get two elements from the first byte (which is 251 | // encoded differently) and then every varint is a single byte long. 252 | s = make([]int, len(bytes)+1) 253 | 254 | // The first varint is 40*value1 + value2: 255 | // According to this packing, value1 can take the values 0, 1 and 2 only. 256 | // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2, 257 | // then there are no restrictions on value2. 258 | v, offset, err := parseBase128Int(bytes, 0) 259 | if err != nil { 260 | return 261 | } 262 | if v < 80 { 263 | s[0] = v / 40 264 | s[1] = v % 40 265 | } else { 266 | s[0] = 2 267 | s[1] = v - 80 268 | } 269 | 270 | i := 2 271 | for ; offset < len(bytes); i++ { 272 | v, offset, err = parseBase128Int(bytes, offset) 273 | if err != nil { 274 | return 275 | } 276 | s[i] = v 277 | } 278 | s = s[0:i] 279 | return 280 | } 281 | 282 | // ENUMERATED 283 | 284 | // An Enumerated is represented as a plain int. 285 | type Enumerated int 286 | 287 | // FLAG 288 | 289 | // A Flag accepts any data and is set to true if present. 290 | type Flag bool 291 | 292 | // parseBase128Int parses a base-128 encoded int from the given offset in the 293 | // given byte slice. It returns the value and the new offset. 294 | func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) { 295 | offset = initOffset 296 | for shifted := 0; offset < len(bytes); shifted++ { 297 | if shifted == 4 { 298 | err = StructuralError{"base 128 integer too large"} 299 | return 300 | } 301 | ret <<= 7 302 | b := bytes[offset] 303 | ret |= int(b & 0x7f) 304 | offset++ 305 | if b&0x80 == 0 { 306 | return 307 | } 308 | } 309 | err = SyntaxError{"truncated base 128 integer"} 310 | return 311 | } 312 | 313 | // UTCTime 314 | 315 | func parseUTCTime(bytes []byte) (ret time.Time, err error) { 316 | s := string(bytes) 317 | 318 | formatStr := "0601021504Z0700" 319 | ret, err = time.Parse(formatStr, s) 320 | if err != nil { 321 | formatStr = "060102150405Z0700" 322 | ret, err = time.Parse(formatStr, s) 323 | } 324 | if err != nil { 325 | return 326 | } 327 | 328 | if serialized := ret.Format(formatStr); serialized != s { 329 | // Apple uses a non-standard format (with decimals) 330 | // err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized) 331 | // return 332 | } 333 | 334 | if ret.Year() >= 2050 { 335 | // UTCTime only encodes times prior to 2050. See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1 336 | ret = ret.AddDate(-100, 0, 0) 337 | } 338 | 339 | return 340 | } 341 | 342 | // parseGeneralizedTime parses the GeneralizedTime from the given byte slice 343 | // and returns the resulting time. 344 | func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) { 345 | const formatStr = "20060102150405Z0700" 346 | s := string(bytes) 347 | 348 | if ret, err = time.Parse(formatStr, s); err != nil { 349 | return 350 | } 351 | 352 | if serialized := ret.Format(formatStr); serialized != s { 353 | // err = fmt.Errorf("asn1: time did not serialize back to the original value and may be invalid: given %q, but serialized as %q", s, serialized) 354 | } 355 | 356 | return 357 | } 358 | 359 | // PrintableString 360 | 361 | // parsePrintableString parses a ASN.1 PrintableString from the given byte 362 | // array and returns it. 363 | func parsePrintableString(bytes []byte) (ret string, err error) { 364 | for _, b := range bytes { 365 | if !isPrintable(b) { 366 | err = SyntaxError{"PrintableString contains invalid character"} 367 | return 368 | } 369 | } 370 | ret = string(bytes) 371 | return 372 | } 373 | 374 | // isPrintable reports whether the given b is in the ASN.1 PrintableString set. 375 | func isPrintable(b byte) bool { 376 | return 'a' <= b && b <= 'z' || 377 | 'A' <= b && b <= 'Z' || 378 | '0' <= b && b <= '9' || 379 | '\'' <= b && b <= ')' || 380 | '+' <= b && b <= '/' || 381 | b == ' ' || 382 | b == ':' || 383 | b == '=' || 384 | b == '?' || 385 | // This is technically not allowed in a PrintableString. 386 | // However, x509 certificates with wildcard strings don't 387 | // always use the correct string type so we permit it. 388 | b == '*' 389 | } 390 | 391 | // IA5String 392 | 393 | // parseIA5String parses a ASN.1 IA5String (ASCII string) from the given 394 | // byte slice and returns it. 395 | func parseIA5String(bytes []byte) (ret string, err error) { 396 | for _, b := range bytes { 397 | if b >= 0x80 { 398 | err = SyntaxError{"IA5String contains invalid character"} 399 | return 400 | } 401 | } 402 | ret = string(bytes) 403 | return 404 | } 405 | 406 | // T61String 407 | 408 | // parseT61String parses a ASN.1 T61String (8-bit clean string) from the given 409 | // byte slice and returns it. 410 | func parseT61String(bytes []byte) (ret string, err error) { 411 | return string(bytes), nil 412 | } 413 | 414 | // UTF8String 415 | 416 | // parseUTF8String parses a ASN.1 UTF8String (raw UTF-8) from the given byte 417 | // array and returns it. 418 | func parseUTF8String(bytes []byte) (ret string, err error) { 419 | if !utf8.Valid(bytes) { 420 | return "", errors.New("asn1: invalid UTF-8 string") 421 | } 422 | return string(bytes), nil 423 | } 424 | 425 | // A RawValue represents an undecoded ASN.1 object. 426 | type RawValue struct { 427 | Class, Tag int 428 | IsCompound bool 429 | Bytes []byte 430 | FullBytes []byte // includes the tag and length 431 | } 432 | 433 | // RawContent is used to signal that the undecoded, DER data needs to be 434 | // preserved for a struct. To use it, the first field of the struct must have 435 | // this type. It's an error for any of the other fields to have this type. 436 | type RawContent []byte 437 | 438 | // Tagging 439 | 440 | // parseTagAndLength parses an ASN.1 tag and length pair from the given offset 441 | // into a byte slice. It returns the parsed data and the new offset. SET and 442 | // SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we 443 | // don't distinguish between ordered and unordered objects in this code. 444 | func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset int, err error) { 445 | offset = initOffset 446 | // parseTagAndLength should not be called without at least a single 447 | // byte to read. Thus this check is for robustness: 448 | if offset >= len(bytes) { 449 | err = errors.New("asn1: internal error in parseTagAndLength") 450 | return 451 | } 452 | b := bytes[offset] 453 | offset++ 454 | ret.class = int(b >> 6) 455 | ret.isCompound = b&0x20 == 0x20 456 | ret.tag = int(b & 0x1f) 457 | 458 | // If the bottom five bits are set, then the tag number is actually base 128 459 | // encoded afterwards 460 | if ret.tag == 0x1f { 461 | ret.tag, offset, err = parseBase128Int(bytes, offset) 462 | if err != nil { 463 | return 464 | } 465 | } 466 | if offset >= len(bytes) { 467 | err = SyntaxError{"truncated tag or length"} 468 | return 469 | } 470 | b = bytes[offset] 471 | offset++ 472 | if b&0x80 == 0 { 473 | // The length is encoded in the bottom 7 bits. 474 | ret.length = int(b & 0x7f) 475 | } else { 476 | // Bottom 7 bits give the number of length bytes to follow. 477 | numBytes := int(b & 0x7f) 478 | if numBytes == 0 { 479 | err = SyntaxError{"indefinite length found (not DER)"} 480 | return 481 | } 482 | ret.length = 0 483 | for i := 0; i < numBytes; i++ { 484 | if offset >= len(bytes) { 485 | err = SyntaxError{"truncated tag or length"} 486 | return 487 | } 488 | b = bytes[offset] 489 | offset++ 490 | if ret.length >= 1<<23 { 491 | // We can't shift ret.length up without 492 | // overflowing. 493 | err = StructuralError{"length too large"} 494 | return 495 | } 496 | ret.length <<= 8 497 | ret.length |= int(b) 498 | if ret.length == 0 { 499 | // DER requires that lengths be minimal. 500 | err = StructuralError{"superfluous leading zeros in length"} 501 | return 502 | } 503 | } 504 | // Short lengths must be encoded in short form. 505 | if ret.length < 0x80 { 506 | err = StructuralError{"non-minimal length"} 507 | return 508 | } 509 | } 510 | 511 | return 512 | } 513 | 514 | // parseSequenceOf is used for SEQUENCE OF and SET OF values. It tries to parse 515 | // a number of ASN.1 values from the given byte slice and returns them as a 516 | // slice of Go values of the given type. 517 | func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type) (ret reflect.Value, err error) { 518 | expectedTag, compoundType, ok := getUniversalType(elemType) 519 | if !ok { 520 | err = StructuralError{"unknown Go type for slice"} 521 | return 522 | } 523 | 524 | // First we iterate over the input and count the number of elements, 525 | // checking that the types are correct in each case. 526 | numElements := 0 527 | for offset := 0; offset < len(bytes); { 528 | var t tagAndLength 529 | t, offset, err = parseTagAndLength(bytes, offset) 530 | if err != nil { 531 | return 532 | } 533 | switch t.tag { 534 | case TagIA5String, TagGeneralString, TagT61String, TagUTF8String: 535 | // We pretend that various other string types are 536 | // PRINTABLE STRINGs so that a sequence of them can be 537 | // parsed into a []string. 538 | t.tag = TagPrintableString 539 | case TagGeneralizedTime, TagUTCTime: 540 | // Likewise, both time types are treated the same. 541 | t.tag = TagUTCTime 542 | } 543 | 544 | if t.class != ClassUniversal || t.isCompound != compoundType || t.tag != expectedTag { 545 | err = StructuralError{"sequence tag mismatch"} 546 | return 547 | } 548 | if invalidLength(offset, t.length, len(bytes)) { 549 | err = SyntaxError{"truncated sequence"} 550 | return 551 | } 552 | offset += t.length 553 | numElements++ 554 | } 555 | ret = reflect.MakeSlice(sliceType, numElements, numElements) 556 | params := fieldParameters{} 557 | offset := 0 558 | for i := 0; i < numElements; i++ { 559 | offset, err = parseField(ret.Index(i), bytes, offset, params) 560 | if err != nil { 561 | return 562 | } 563 | } 564 | return 565 | } 566 | 567 | var ( 568 | bitStringType = reflect.TypeOf(BitString{}) 569 | objectIdentifierType = reflect.TypeOf(ObjectIdentifier{}) 570 | enumeratedType = reflect.TypeOf(Enumerated(0)) 571 | flagType = reflect.TypeOf(Flag(false)) 572 | timeType = reflect.TypeOf(time.Time{}) 573 | rawValueType = reflect.TypeOf(RawValue{}) 574 | rawContentsType = reflect.TypeOf(RawContent(nil)) 575 | bigIntType = reflect.TypeOf(new(big.Int)) 576 | ) 577 | 578 | // invalidLength returns true iff offset + length > sliceLength, or if the 579 | // addition would overflow. 580 | func invalidLength(offset, length, sliceLength int) bool { 581 | return offset+length < offset || offset+length > sliceLength 582 | } 583 | 584 | // parseField is the main parsing function. Given a byte slice and an offset 585 | // into the array, it will try to parse a suitable ASN.1 value out and store it 586 | // in the given Value. 587 | func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParameters) (offset int, err error) { 588 | offset = initOffset 589 | fieldType := v.Type() 590 | 591 | // If we have run out of data, it may be that there are optional elements at the end. 592 | if offset == len(bytes) { 593 | if !setDefaultValue(v, params) { 594 | err = SyntaxError{"sequence truncated"} 595 | } 596 | return 597 | } 598 | 599 | // Deal with raw values. 600 | if fieldType == rawValueType { 601 | var t tagAndLength 602 | t, offset, err = parseTagAndLength(bytes, offset) 603 | if err != nil { 604 | return 605 | } 606 | if invalidLength(offset, t.length, len(bytes)) { 607 | err = SyntaxError{"data truncated"} 608 | return 609 | } 610 | result := RawValue{t.class, t.tag, t.isCompound, bytes[offset : offset+t.length], bytes[initOffset : offset+t.length]} 611 | offset += t.length 612 | v.Set(reflect.ValueOf(result)) 613 | return 614 | } 615 | 616 | // Deal with the ANY type. 617 | if ifaceType := fieldType; ifaceType.Kind() == reflect.Interface && ifaceType.NumMethod() == 0 { 618 | var t tagAndLength 619 | t, offset, err = parseTagAndLength(bytes, offset) 620 | if err != nil { 621 | return 622 | } 623 | if invalidLength(offset, t.length, len(bytes)) { 624 | err = SyntaxError{"data truncated"} 625 | return 626 | } 627 | var result interface{} 628 | if !t.isCompound && t.class == ClassUniversal { 629 | innerBytes := bytes[offset : offset+t.length] 630 | switch t.tag { 631 | case TagPrintableString: 632 | result, err = parsePrintableString(innerBytes) 633 | case TagIA5String: 634 | result, err = parseIA5String(innerBytes) 635 | case TagT61String: 636 | result, err = parseT61String(innerBytes) 637 | case TagUTF8String: 638 | result, err = parseUTF8String(innerBytes) 639 | case TagInteger: 640 | result, err = parseInt64(innerBytes) 641 | case TagBitString: 642 | result, err = parseBitString(innerBytes) 643 | case TagOID: 644 | result, err = parseObjectIdentifier(innerBytes) 645 | case TagUTCTime: 646 | result, err = parseUTCTime(innerBytes) 647 | case TagGeneralizedTime: 648 | result, err = parseGeneralizedTime(innerBytes) 649 | case TagOctetString: 650 | result = innerBytes 651 | default: 652 | // If we don't know how to handle the type, we just leave Value as nil. 653 | } 654 | } 655 | offset += t.length 656 | if err != nil { 657 | return 658 | } 659 | if result != nil { 660 | v.Set(reflect.ValueOf(result)) 661 | } 662 | return 663 | } 664 | universalTag, compoundType, ok1 := getUniversalType(fieldType) 665 | if !ok1 { 666 | err = StructuralError{fmt.Sprintf("unknown Go type: %v", fieldType)} 667 | return 668 | } 669 | 670 | t, offset, err := parseTagAndLength(bytes, offset) 671 | if err != nil { 672 | return 673 | } 674 | if params.explicit { 675 | expectedClass := ClassContextSpecific 676 | if params.application { 677 | expectedClass = ClassApplication 678 | } 679 | if offset == len(bytes) { 680 | err = StructuralError{"explicit tag has no child"} 681 | return 682 | } 683 | if t.class == expectedClass && t.tag == *params.tag && (t.length == 0 || t.isCompound) { 684 | if t.length > 0 { 685 | t, offset, err = parseTagAndLength(bytes, offset) 686 | if err != nil { 687 | return 688 | } 689 | } else { 690 | if fieldType != flagType { 691 | err = StructuralError{"zero length explicit tag was not an asn1.Flag"} 692 | return 693 | } 694 | v.SetBool(true) 695 | return 696 | } 697 | } else { 698 | // The tags didn't match, it might be an optional element. 699 | ok := setDefaultValue(v, params) 700 | if ok { 701 | offset = initOffset 702 | } else { 703 | err = StructuralError{"explicitly tagged member didn't match"} 704 | } 705 | return 706 | } 707 | } 708 | 709 | // Special case for strings: all the ASN.1 string types map to the Go 710 | // type string. getUniversalType returns the tag for PrintableString 711 | // when it sees a string, so if we see a different string type on the 712 | // wire, we change the universal type to match. 713 | if universalTag == TagPrintableString { 714 | if t.class == ClassUniversal { 715 | switch t.tag { 716 | case TagIA5String, TagGeneralString, TagT61String, TagUTF8String: 717 | universalTag = t.tag 718 | } 719 | } else if params.stringType != 0 { 720 | universalTag = params.stringType 721 | } 722 | } 723 | 724 | // Special case for time: UTCTime and GeneralizedTime both map to the 725 | // Go type time.Time. 726 | if universalTag == TagUTCTime && t.tag == TagGeneralizedTime && t.class == ClassUniversal { 727 | universalTag = TagGeneralizedTime 728 | } 729 | 730 | if params.set { 731 | universalTag = TagSet 732 | } 733 | 734 | expectedClass := ClassUniversal 735 | expectedTag := universalTag 736 | 737 | if !params.explicit && params.tag != nil { 738 | expectedClass = ClassContextSpecific 739 | expectedTag = *params.tag 740 | } 741 | 742 | if !params.explicit && params.application && params.tag != nil { 743 | expectedClass = ClassApplication 744 | expectedTag = *params.tag 745 | } 746 | 747 | // We have unwrapped any explicit tagging at this point. 748 | if t.class != expectedClass || t.tag != expectedTag || t.isCompound != compoundType { 749 | // Tags don't match. Again, it could be an optional element. 750 | ok := setDefaultValue(v, params) 751 | if ok { 752 | offset = initOffset 753 | } else { 754 | err = StructuralError{fmt.Sprintf("tags don't match (%d vs %+v) %+v %s @%d", expectedTag, t, params, fieldType.Name(), offset)} 755 | } 756 | return 757 | } 758 | if invalidLength(offset, t.length, len(bytes)) { 759 | err = SyntaxError{"data truncated"} 760 | return 761 | } 762 | innerBytes := bytes[offset : offset+t.length] 763 | offset += t.length 764 | 765 | // We deal with the structures defined in this package first. 766 | switch fieldType { 767 | case objectIdentifierType: 768 | newSlice, err1 := parseObjectIdentifier(innerBytes) 769 | v.Set(reflect.MakeSlice(v.Type(), len(newSlice), len(newSlice))) 770 | if err1 == nil { 771 | reflect.Copy(v, reflect.ValueOf(newSlice)) 772 | } 773 | err = err1 774 | return 775 | case bitStringType: 776 | bs, err1 := parseBitString(innerBytes) 777 | if err1 == nil { 778 | v.Set(reflect.ValueOf(bs)) 779 | } 780 | err = err1 781 | return 782 | case timeType: 783 | var time time.Time 784 | var err1 error 785 | if universalTag == TagUTCTime { 786 | time, err1 = parseUTCTime(innerBytes) 787 | } else { 788 | time, err1 = parseGeneralizedTime(innerBytes) 789 | } 790 | if err1 == nil { 791 | v.Set(reflect.ValueOf(time)) 792 | } 793 | err = err1 794 | return 795 | case enumeratedType: 796 | parsedInt, err1 := parseInt32(innerBytes) 797 | if err1 == nil { 798 | v.SetInt(int64(parsedInt)) 799 | } 800 | err = err1 801 | return 802 | case flagType: 803 | v.SetBool(true) 804 | return 805 | case bigIntType: 806 | parsedInt, err1 := parseBigInt(innerBytes) 807 | if err1 == nil { 808 | v.Set(reflect.ValueOf(parsedInt)) 809 | } 810 | err = err1 811 | return 812 | } 813 | switch val := v; val.Kind() { 814 | case reflect.Bool: 815 | parsedBool, err1 := parseBool(innerBytes) 816 | if err1 == nil { 817 | val.SetBool(parsedBool) 818 | } 819 | err = err1 820 | return 821 | case reflect.Int, reflect.Int32, reflect.Int64: 822 | if val.Type().Size() == 4 { 823 | parsedInt, err1 := parseInt32(innerBytes) 824 | if err1 == nil { 825 | val.SetInt(int64(parsedInt)) 826 | } 827 | err = err1 828 | } else { 829 | parsedInt, err1 := parseInt64(innerBytes) 830 | if err1 == nil { 831 | val.SetInt(parsedInt) 832 | } 833 | err = err1 834 | } 835 | return 836 | // TODO(dfc) Add support for the remaining integer types 837 | case reflect.Struct: 838 | structType := fieldType 839 | 840 | if structType.NumField() > 0 && 841 | structType.Field(0).Type == rawContentsType { 842 | bytes := bytes[initOffset:offset] 843 | val.Field(0).Set(reflect.ValueOf(RawContent(bytes))) 844 | } 845 | 846 | innerOffset := 0 847 | for i := 0; i < structType.NumField(); i++ { 848 | field := structType.Field(i) 849 | if i == 0 && field.Type == rawContentsType { 850 | continue 851 | } 852 | innerOffset, err = parseField(val.Field(i), innerBytes, innerOffset, parseFieldParameters(field.Tag.Get("asn1"))) 853 | if err != nil { 854 | return 855 | } 856 | } 857 | // We allow extra bytes at the end of the SEQUENCE because 858 | // adding elements to the end has been used in X.509 as the 859 | // version numbers have increased. 860 | return 861 | case reflect.Slice: 862 | sliceType := fieldType 863 | if sliceType.Elem().Kind() == reflect.Uint8 { 864 | val.Set(reflect.MakeSlice(sliceType, len(innerBytes), len(innerBytes))) 865 | reflect.Copy(val, reflect.ValueOf(innerBytes)) 866 | return 867 | } 868 | newSlice, err1 := parseSequenceOf(innerBytes, sliceType, sliceType.Elem()) 869 | if err1 == nil { 870 | val.Set(newSlice) 871 | } 872 | err = err1 873 | return 874 | case reflect.String: 875 | var v string 876 | switch universalTag { 877 | case TagPrintableString: 878 | v, err = parsePrintableString(innerBytes) 879 | case TagIA5String: 880 | v, err = parseIA5String(innerBytes) 881 | case TagT61String: 882 | v, err = parseT61String(innerBytes) 883 | case TagUTF8String: 884 | v, err = parseUTF8String(innerBytes) 885 | case TagGeneralString: 886 | // GeneralString is specified in ISO-2022/ECMA-35, 887 | // A brief review suggests that it includes structures 888 | // that allow the encoding to change midstring and 889 | // such. We give up and pass it as an 8-bit string. 890 | v, err = parseT61String(innerBytes) 891 | default: 892 | err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)} 893 | } 894 | if err == nil { 895 | val.SetString(v) 896 | } 897 | return 898 | } 899 | err = StructuralError{"unsupported: " + v.Type().String()} 900 | return 901 | } 902 | 903 | // canHaveDefaultValue reports whether k is a Kind that we will set a default 904 | // value for. (A signed integer, essentially.) 905 | func canHaveDefaultValue(k reflect.Kind) bool { 906 | switch k { 907 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 908 | return true 909 | } 910 | 911 | return false 912 | } 913 | 914 | // setDefaultValue is used to install a default value, from a tag string, into 915 | // a Value. It is successful if the field was optional, even if a default value 916 | // wasn't provided or it failed to install it into the Value. 917 | func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { 918 | if !params.optional { 919 | return 920 | } 921 | ok = true 922 | if params.defaultValue == nil { 923 | return 924 | } 925 | if canHaveDefaultValue(v.Kind()) { 926 | v.SetInt(*params.defaultValue) 927 | } 928 | return 929 | } 930 | 931 | // Unmarshal parses the DER-encoded ASN.1 data structure b 932 | // and uses the reflect package to fill in an arbitrary value pointed at by val. 933 | // Because Unmarshal uses the reflect package, the structs 934 | // being written to must use upper case field names. 935 | // 936 | // An ASN.1 INTEGER can be written to an int, int32, int64, 937 | // or *big.Int (from the math/big package). 938 | // If the encoded value does not fit in the Go type, 939 | // Unmarshal returns a parse error. 940 | // 941 | // An ASN.1 BIT STRING can be written to a BitString. 942 | // 943 | // An ASN.1 OCTET STRING can be written to a []byte. 944 | // 945 | // An ASN.1 OBJECT IDENTIFIER can be written to an 946 | // ObjectIdentifier. 947 | // 948 | // An ASN.1 ENUMERATED can be written to an Enumerated. 949 | // 950 | // An ASN.1 UTCTIME or GENERALIZEDTIME can be written to a time.Time. 951 | // 952 | // An ASN.1 PrintableString or IA5String can be written to a string. 953 | // 954 | // Any of the above ASN.1 values can be written to an interface{}. 955 | // The value stored in the interface has the corresponding Go type. 956 | // For integers, that type is int64. 957 | // 958 | // An ASN.1 SEQUENCE OF x or SET OF x can be written 959 | // to a slice if an x can be written to the slice's element type. 960 | // 961 | // An ASN.1 SEQUENCE or SET can be written to a struct 962 | // if each of the elements in the sequence can be 963 | // written to the corresponding element in the struct. 964 | // 965 | // The following tags on struct fields have special meaning to Unmarshal: 966 | // 967 | // application specifies that a APPLICATION tag is used 968 | // default:x sets the default value for optional integer fields 969 | // explicit specifies that an additional, explicit tag wraps the implicit one 970 | // optional marks the field as ASN.1 OPTIONAL 971 | // set causes a SET, rather than a SEQUENCE type to be expected 972 | // tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC 973 | // 974 | // If the type of the first field of a structure is RawContent then the raw 975 | // ASN1 contents of the struct will be stored in it. 976 | // 977 | // If the type name of a slice element ends with "SET" then it's treated as if 978 | // the "set" tag was set on it. This can be used with nested slices where a 979 | // struct tag cannot be given. 980 | // 981 | // Other ASN.1 types are not supported; if it encounters them, 982 | // Unmarshal returns a parse error. 983 | func Unmarshal(b []byte, val interface{}) (rest []byte, err error) { 984 | return UnmarshalWithParams(b, val, "") 985 | } 986 | 987 | // UnmarshalWithParams allows field parameters to be specified for the 988 | // top-level element. The form of the params is the same as the field tags. 989 | func UnmarshalWithParams(b []byte, val interface{}, params string) (rest []byte, err error) { 990 | v := reflect.ValueOf(val).Elem() 991 | offset, err := parseField(v, b, 0, parseFieldParameters(params)) 992 | if err != nil { 993 | return nil, err 994 | } 995 | return b[offset:], nil 996 | } 997 | -------------------------------------------------------------------------------- /encoding/asn1/asn1_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 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 asn1 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "math/big" 11 | "reflect" 12 | "strings" 13 | "testing" 14 | "time" 15 | ) 16 | 17 | type boolTest struct { 18 | in []byte 19 | ok bool 20 | out bool 21 | } 22 | 23 | var boolTestData = []boolTest{ 24 | {[]byte{0x00}, true, false}, 25 | {[]byte{0xff}, true, true}, 26 | {[]byte{0x00, 0x00}, false, false}, 27 | {[]byte{0xff, 0xff}, false, false}, 28 | {[]byte{0x01}, false, false}, 29 | } 30 | 31 | func TestParseBool(t *testing.T) { 32 | for i, test := range boolTestData { 33 | ret, err := parseBool(test.in) 34 | if (err == nil) != test.ok { 35 | t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) 36 | } 37 | if test.ok && ret != test.out { 38 | t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) 39 | } 40 | } 41 | } 42 | 43 | type int64Test struct { 44 | in []byte 45 | ok bool 46 | out int64 47 | } 48 | 49 | var int64TestData = []int64Test{ 50 | {[]byte{0x00}, true, 0}, 51 | {[]byte{0x7f}, true, 127}, 52 | {[]byte{0x00, 0x80}, true, 128}, 53 | {[]byte{0x01, 0x00}, true, 256}, 54 | {[]byte{0x80}, true, -128}, 55 | {[]byte{0xff, 0x7f}, true, -129}, 56 | {[]byte{0xff}, true, -1}, 57 | {[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, true, -9223372036854775808}, 58 | {[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, false, 0}, 59 | {[]byte{}, false, 0}, 60 | {[]byte{0x00, 0x7f}, false, 0}, 61 | {[]byte{0xff, 0xf0}, false, 0}, 62 | } 63 | 64 | func TestParseInt64(t *testing.T) { 65 | for i, test := range int64TestData { 66 | ret, err := parseInt64(test.in) 67 | if (err == nil) != test.ok { 68 | t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) 69 | } 70 | if test.ok && ret != test.out { 71 | t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) 72 | } 73 | } 74 | } 75 | 76 | type int32Test struct { 77 | in []byte 78 | ok bool 79 | out int32 80 | } 81 | 82 | var int32TestData = []int32Test{ 83 | {[]byte{0x00}, true, 0}, 84 | {[]byte{0x7f}, true, 127}, 85 | {[]byte{0x00, 0x80}, true, 128}, 86 | {[]byte{0x01, 0x00}, true, 256}, 87 | {[]byte{0x80}, true, -128}, 88 | {[]byte{0xff, 0x7f}, true, -129}, 89 | {[]byte{0xff}, true, -1}, 90 | {[]byte{0x80, 0x00, 0x00, 0x00}, true, -2147483648}, 91 | {[]byte{0x80, 0x00, 0x00, 0x00, 0x00}, false, 0}, 92 | {[]byte{}, false, 0}, 93 | {[]byte{0x00, 0x7f}, false, 0}, 94 | {[]byte{0xff, 0xf0}, false, 0}, 95 | } 96 | 97 | func TestParseInt32(t *testing.T) { 98 | for i, test := range int32TestData { 99 | ret, err := parseInt32(test.in) 100 | if (err == nil) != test.ok { 101 | t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) 102 | } 103 | if test.ok && int32(ret) != test.out { 104 | t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) 105 | } 106 | } 107 | } 108 | 109 | var bigIntTests = []struct { 110 | in []byte 111 | ok bool 112 | base10 string 113 | }{ 114 | {[]byte{0xff}, true, "-1"}, 115 | {[]byte{0x00}, true, "0"}, 116 | {[]byte{0x01}, true, "1"}, 117 | {[]byte{0x00, 0xff}, true, "255"}, 118 | {[]byte{0xff, 0x00}, true, "-256"}, 119 | {[]byte{0x01, 0x00}, true, "256"}, 120 | {[]byte{}, false, ""}, 121 | {[]byte{0x00, 0x7f}, false, ""}, 122 | {[]byte{0xff, 0xf0}, false, ""}, 123 | } 124 | 125 | func TestParseBigInt(t *testing.T) { 126 | for i, test := range bigIntTests { 127 | ret, err := parseBigInt(test.in) 128 | if (err == nil) != test.ok { 129 | t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) 130 | } 131 | if test.ok { 132 | if ret.String() != test.base10 { 133 | t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10) 134 | } 135 | fw := newForkableWriter() 136 | marshalBigInt(fw, ret) 137 | result := fw.Bytes() 138 | if !bytes.Equal(result, test.in) { 139 | t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in) 140 | } 141 | } 142 | } 143 | } 144 | 145 | type bitStringTest struct { 146 | in []byte 147 | ok bool 148 | out []byte 149 | bitLength int 150 | } 151 | 152 | var bitStringTestData = []bitStringTest{ 153 | {[]byte{}, false, []byte{}, 0}, 154 | {[]byte{0x00}, true, []byte{}, 0}, 155 | {[]byte{0x07, 0x00}, true, []byte{0x00}, 1}, 156 | {[]byte{0x07, 0x01}, false, []byte{}, 0}, 157 | {[]byte{0x07, 0x40}, false, []byte{}, 0}, 158 | {[]byte{0x08, 0x00}, false, []byte{}, 0}, 159 | } 160 | 161 | func TestBitString(t *testing.T) { 162 | for i, test := range bitStringTestData { 163 | ret, err := parseBitString(test.in) 164 | if (err == nil) != test.ok { 165 | t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) 166 | } 167 | if err == nil { 168 | if test.bitLength != ret.BitLength || !bytes.Equal(ret.Bytes, test.out) { 169 | t.Errorf("#%d: Bad result: %v (expected %v %v)", i, ret, test.out, test.bitLength) 170 | } 171 | } 172 | } 173 | } 174 | 175 | func TestBitStringAt(t *testing.T) { 176 | bs := BitString{[]byte{0x82, 0x40}, 16} 177 | if bs.At(0) != 1 { 178 | t.Error("#1: Failed") 179 | } 180 | if bs.At(1) != 0 { 181 | t.Error("#2: Failed") 182 | } 183 | if bs.At(6) != 1 { 184 | t.Error("#3: Failed") 185 | } 186 | if bs.At(9) != 1 { 187 | t.Error("#4: Failed") 188 | } 189 | if bs.At(-1) != 0 { 190 | t.Error("#5: Failed") 191 | } 192 | if bs.At(17) != 0 { 193 | t.Error("#6: Failed") 194 | } 195 | } 196 | 197 | type bitStringRightAlignTest struct { 198 | in []byte 199 | inlen int 200 | out []byte 201 | } 202 | 203 | var bitStringRightAlignTests = []bitStringRightAlignTest{ 204 | {[]byte{0x80}, 1, []byte{0x01}}, 205 | {[]byte{0x80, 0x80}, 9, []byte{0x01, 0x01}}, 206 | {[]byte{}, 0, []byte{}}, 207 | {[]byte{0xce}, 8, []byte{0xce}}, 208 | {[]byte{0xce, 0x47}, 16, []byte{0xce, 0x47}}, 209 | {[]byte{0x34, 0x50}, 12, []byte{0x03, 0x45}}, 210 | } 211 | 212 | func TestBitStringRightAlign(t *testing.T) { 213 | for i, test := range bitStringRightAlignTests { 214 | bs := BitString{test.in, test.inlen} 215 | out := bs.RightAlign() 216 | if !bytes.Equal(out, test.out) { 217 | t.Errorf("#%d got: %x want: %x", i, out, test.out) 218 | } 219 | } 220 | } 221 | 222 | type objectIdentifierTest struct { 223 | in []byte 224 | ok bool 225 | out []int 226 | } 227 | 228 | var objectIdentifierTestData = []objectIdentifierTest{ 229 | {[]byte{}, false, []int{}}, 230 | {[]byte{85}, true, []int{2, 5}}, 231 | {[]byte{85, 0x02}, true, []int{2, 5, 2}}, 232 | {[]byte{85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}}, 233 | {[]byte{0x81, 0x34, 0x03}, true, []int{2, 100, 3}}, 234 | {[]byte{85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}}, 235 | } 236 | 237 | func TestObjectIdentifier(t *testing.T) { 238 | for i, test := range objectIdentifierTestData { 239 | ret, err := parseObjectIdentifier(test.in) 240 | if (err == nil) != test.ok { 241 | t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) 242 | } 243 | if err == nil { 244 | if !reflect.DeepEqual(test.out, ret) { 245 | t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out) 246 | } 247 | } 248 | } 249 | 250 | if s := ObjectIdentifier([]int{1, 2, 3, 4}).String(); s != "1.2.3.4" { 251 | t.Errorf("bad ObjectIdentifier.String(). Got %s, want 1.2.3.4", s) 252 | } 253 | } 254 | 255 | type timeTest struct { 256 | in string 257 | ok bool 258 | out time.Time 259 | } 260 | 261 | var utcTestData = []timeTest{ 262 | {"910506164540-0700", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", -7*60*60))}, 263 | {"910506164540+0730", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", 7*60*60+30*60))}, 264 | {"910506234540Z", true, time.Date(1991, 05, 06, 23, 45, 40, 0, time.UTC)}, 265 | {"9105062345Z", true, time.Date(1991, 05, 06, 23, 45, 0, 0, time.UTC)}, 266 | {"5105062345Z", true, time.Date(1951, 05, 06, 23, 45, 0, 0, time.UTC)}, 267 | {"a10506234540Z", false, time.Time{}}, 268 | {"91a506234540Z", false, time.Time{}}, 269 | {"9105a6234540Z", false, time.Time{}}, 270 | {"910506a34540Z", false, time.Time{}}, 271 | {"910506334a40Z", false, time.Time{}}, 272 | {"91050633444aZ", false, time.Time{}}, 273 | {"910506334461Z", false, time.Time{}}, 274 | {"910506334400Za", false, time.Time{}}, 275 | /* These are invalid times. However, the time package normalises times 276 | * and they were accepted in some versions. See #11134. */ 277 | {"000100000000Z", false, time.Time{}}, 278 | {"101302030405Z", false, time.Time{}}, 279 | {"100002030405Z", false, time.Time{}}, 280 | {"100100030405Z", false, time.Time{}}, 281 | {"100132030405Z", false, time.Time{}}, 282 | {"100231030405Z", false, time.Time{}}, 283 | {"100102240405Z", false, time.Time{}}, 284 | {"100102036005Z", false, time.Time{}}, 285 | {"100102030460Z", false, time.Time{}}, 286 | {"-100102030410Z", false, time.Time{}}, 287 | {"10-0102030410Z", false, time.Time{}}, 288 | {"10-0002030410Z", false, time.Time{}}, 289 | {"1001-02030410Z", false, time.Time{}}, 290 | {"100102-030410Z", false, time.Time{}}, 291 | {"10010203-0410Z", false, time.Time{}}, 292 | {"1001020304-10Z", false, time.Time{}}, 293 | } 294 | 295 | func TestUTCTime(t *testing.T) { 296 | for i, test := range utcTestData { 297 | ret, err := parseUTCTime([]byte(test.in)) 298 | if err != nil { 299 | if test.ok { 300 | t.Errorf("#%d: parseUTCTime(%q) = error %v", i, test.in, err) 301 | } 302 | continue 303 | } 304 | if !test.ok { 305 | t.Errorf("#%d: parseUTCTime(%q) succeeded, should have failed", i, test.in) 306 | continue 307 | } 308 | const format = "Jan _2 15:04:05 -0700 2006" // ignore zone name, just offset 309 | have := ret.Format(format) 310 | want := test.out.Format(format) 311 | if have != want { 312 | t.Errorf("#%d: parseUTCTime(%q) = %s, want %s", i, test.in, have, want) 313 | } 314 | } 315 | } 316 | 317 | var generalizedTimeTestData = []timeTest{ 318 | {"20100102030405Z", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.UTC)}, 319 | {"20100102030405", false, time.Time{}}, 320 | {"20100102030405+0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}, 321 | {"20100102030405-0607", true, time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", -6*60*60-7*60))}, 322 | /* These are invalid times. However, the time package normalises times 323 | * and they were accepted in some versions. See #11134. */ 324 | {"00000100000000Z", false, time.Time{}}, 325 | {"20101302030405Z", false, time.Time{}}, 326 | {"20100002030405Z", false, time.Time{}}, 327 | {"20100100030405Z", false, time.Time{}}, 328 | {"20100132030405Z", false, time.Time{}}, 329 | {"20100231030405Z", false, time.Time{}}, 330 | {"20100102240405Z", false, time.Time{}}, 331 | {"20100102036005Z", false, time.Time{}}, 332 | {"20100102030460Z", false, time.Time{}}, 333 | {"-20100102030410Z", false, time.Time{}}, 334 | {"2010-0102030410Z", false, time.Time{}}, 335 | {"2010-0002030410Z", false, time.Time{}}, 336 | {"201001-02030410Z", false, time.Time{}}, 337 | {"20100102-030410Z", false, time.Time{}}, 338 | {"2010010203-0410Z", false, time.Time{}}, 339 | {"201001020304-10Z", false, time.Time{}}, 340 | } 341 | 342 | func TestGeneralizedTime(t *testing.T) { 343 | for i, test := range generalizedTimeTestData { 344 | ret, err := parseGeneralizedTime([]byte(test.in)) 345 | if (err == nil) != test.ok { 346 | t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok) 347 | } 348 | if err == nil { 349 | if !reflect.DeepEqual(test.out, ret) { 350 | t.Errorf("#%d: Bad result: %q → %v (expected %v)", i, test.in, ret, test.out) 351 | } 352 | } 353 | } 354 | } 355 | 356 | type tagAndLengthTest struct { 357 | in []byte 358 | ok bool 359 | out tagAndLength 360 | } 361 | 362 | var tagAndLengthData = []tagAndLengthTest{ 363 | {[]byte{0x80, 0x01}, true, tagAndLength{2, 0, 1, false}}, 364 | {[]byte{0xa0, 0x01}, true, tagAndLength{2, 0, 1, true}}, 365 | {[]byte{0x02, 0x00}, true, tagAndLength{0, 2, 0, false}}, 366 | {[]byte{0xfe, 0x00}, true, tagAndLength{3, 30, 0, true}}, 367 | {[]byte{0x1f, 0x01, 0x00}, true, tagAndLength{0, 1, 0, false}}, 368 | {[]byte{0x1f, 0x81, 0x00, 0x00}, true, tagAndLength{0, 128, 0, false}}, 369 | {[]byte{0x1f, 0x81, 0x80, 0x01, 0x00}, true, tagAndLength{0, 0x4001, 0, false}}, 370 | {[]byte{0x00, 0x81, 0x80}, true, tagAndLength{0, 0, 128, false}}, 371 | {[]byte{0x00, 0x82, 0x01, 0x00}, true, tagAndLength{0, 0, 256, false}}, 372 | {[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}}, 373 | {[]byte{0x1f, 0x85}, false, tagAndLength{}}, 374 | {[]byte{0x30, 0x80}, false, tagAndLength{}}, 375 | // Superfluous zeros in the length should be an error. 376 | {[]byte{0xa0, 0x82, 0x00, 0xff}, false, tagAndLength{}}, 377 | // Lengths up to the maximum size of an int should work. 378 | {[]byte{0xa0, 0x84, 0x7f, 0xff, 0xff, 0xff}, true, tagAndLength{2, 0, 0x7fffffff, true}}, 379 | // Lengths that would overflow an int should be rejected. 380 | {[]byte{0xa0, 0x84, 0x80, 0x00, 0x00, 0x00}, false, tagAndLength{}}, 381 | // Long length form may not be used for lengths that fit in short form. 382 | {[]byte{0xa0, 0x81, 0x7f}, false, tagAndLength{}}, 383 | // Tag numbers which would overflow int32 are rejected. (The value below is 2^31.) 384 | {[]byte{0x1f, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00}, false, tagAndLength{}}, 385 | } 386 | 387 | func TestParseTagAndLength(t *testing.T) { 388 | for i, test := range tagAndLengthData { 389 | tagAndLength, _, err := parseTagAndLength(test.in, 0) 390 | if (err == nil) != test.ok { 391 | t.Errorf("#%d: Incorrect error result (did pass? %v, expected: %v)", i, err == nil, test.ok) 392 | } 393 | if err == nil && !reflect.DeepEqual(test.out, tagAndLength) { 394 | t.Errorf("#%d: Bad result: %v (expected %v)", i, tagAndLength, test.out) 395 | } 396 | } 397 | } 398 | 399 | type parseFieldParametersTest struct { 400 | in string 401 | out fieldParameters 402 | } 403 | 404 | func newInt(n int) *int { return &n } 405 | 406 | func newInt64(n int64) *int64 { return &n } 407 | 408 | func newString(s string) *string { return &s } 409 | 410 | func newBool(b bool) *bool { return &b } 411 | 412 | var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{ 413 | {"", fieldParameters{}}, 414 | {"ia5", fieldParameters{stringType: TagIA5String}}, 415 | {"generalized", fieldParameters{timeType: TagGeneralizedTime}}, 416 | {"utc", fieldParameters{timeType: TagUTCTime}}, 417 | {"printable", fieldParameters{stringType: TagPrintableString}}, 418 | {"optional", fieldParameters{optional: true}}, 419 | {"explicit", fieldParameters{explicit: true, tag: new(int)}}, 420 | {"application", fieldParameters{application: true, tag: new(int)}}, 421 | {"optional,explicit", fieldParameters{optional: true, explicit: true, tag: new(int)}}, 422 | {"default:42", fieldParameters{defaultValue: newInt64(42)}}, 423 | {"tag:17", fieldParameters{tag: newInt(17)}}, 424 | {"optional,explicit,default:42,tag:17", fieldParameters{optional: true, explicit: true, defaultValue: newInt64(42), tag: newInt(17)}}, 425 | {"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{true, true, false, newInt64(42), newInt(17), 0, 0, false, false}}, 426 | {"set", fieldParameters{set: true}}, 427 | } 428 | 429 | func TestParseFieldParameters(t *testing.T) { 430 | for i, test := range parseFieldParametersTestData { 431 | f := parseFieldParameters(test.in) 432 | if !reflect.DeepEqual(f, test.out) { 433 | t.Errorf("#%d: Bad result: %v (expected %v)", i, f, test.out) 434 | } 435 | } 436 | } 437 | 438 | type TestObjectIdentifierStruct struct { 439 | OID ObjectIdentifier 440 | } 441 | 442 | type TestContextSpecificTags struct { 443 | A int `asn1:"tag:1"` 444 | } 445 | 446 | type TestContextSpecificTags2 struct { 447 | A int `asn1:"explicit,tag:1"` 448 | B int 449 | } 450 | 451 | type TestContextSpecificTags3 struct { 452 | S string `asn1:"tag:1,utf8"` 453 | } 454 | 455 | type TestElementsAfterString struct { 456 | S string 457 | A, B int 458 | } 459 | 460 | type TestBigInt struct { 461 | X *big.Int 462 | } 463 | 464 | type TestSet struct { 465 | Ints []int `asn1:"set"` 466 | } 467 | 468 | var unmarshalTestData = []struct { 469 | in []byte 470 | out interface{} 471 | }{ 472 | {[]byte{0x02, 0x01, 0x42}, newInt(0x42)}, 473 | {[]byte{0x30, 0x08, 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d}, &TestObjectIdentifierStruct{[]int{1, 2, 840, 113549}}}, 474 | {[]byte{0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0}, &BitString{[]byte{110, 93, 192}, 18}}, 475 | {[]byte{0x30, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &[]int{1, 2, 3}}, 476 | {[]byte{0x02, 0x01, 0x10}, newInt(16)}, 477 | {[]byte{0x13, 0x04, 't', 'e', 's', 't'}, newString("test")}, 478 | {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, newString("test")}, 479 | {[]byte{0x16, 0x04, 't', 'e', 's', 't'}, &RawValue{0, 22, false, []byte("test"), []byte("\x16\x04test")}}, 480 | {[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}}, 481 | {[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}}, 482 | {[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}}, 483 | {[]byte{0x30, 0x03, 0x81, 0x01, '@'}, &TestContextSpecificTags3{"@"}}, 484 | {[]byte{0x01, 0x01, 0x00}, newBool(false)}, 485 | {[]byte{0x01, 0x01, 0xff}, newBool(true)}, 486 | {[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}}, 487 | {[]byte{0x30, 0x05, 0x02, 0x03, 0x12, 0x34, 0x56}, &TestBigInt{big.NewInt(0x123456)}}, 488 | {[]byte{0x30, 0x0b, 0x31, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &TestSet{Ints: []int{1, 2, 3}}}, 489 | } 490 | 491 | func TestUnmarshal(t *testing.T) { 492 | for i, test := range unmarshalTestData { 493 | pv := reflect.New(reflect.TypeOf(test.out).Elem()) 494 | val := pv.Interface() 495 | _, err := Unmarshal(test.in, val) 496 | if err != nil { 497 | t.Errorf("Unmarshal failed at index %d %v", i, err) 498 | } 499 | if !reflect.DeepEqual(val, test.out) { 500 | t.Errorf("#%d:\nhave %#v\nwant %#v", i, val, test.out) 501 | } 502 | } 503 | } 504 | 505 | type Certificate struct { 506 | TBSCertificate TBSCertificate 507 | SignatureAlgorithm AlgorithmIdentifier 508 | SignatureValue BitString 509 | } 510 | 511 | type TBSCertificate struct { 512 | Version int `asn1:"optional,explicit,default:0,tag:0"` 513 | SerialNumber RawValue 514 | SignatureAlgorithm AlgorithmIdentifier 515 | Issuer RDNSequence 516 | Validity Validity 517 | Subject RDNSequence 518 | PublicKey PublicKeyInfo 519 | } 520 | 521 | type AlgorithmIdentifier struct { 522 | Algorithm ObjectIdentifier 523 | } 524 | 525 | type RDNSequence []RelativeDistinguishedNameSET 526 | 527 | type RelativeDistinguishedNameSET []AttributeTypeAndValue 528 | 529 | type AttributeTypeAndValue struct { 530 | Type ObjectIdentifier 531 | Value interface{} 532 | } 533 | 534 | type Validity struct { 535 | NotBefore, NotAfter time.Time 536 | } 537 | 538 | type PublicKeyInfo struct { 539 | Algorithm AlgorithmIdentifier 540 | PublicKey BitString 541 | } 542 | 543 | func TestCertificate(t *testing.T) { 544 | // This is a minimal, self-signed certificate that should parse correctly. 545 | var cert Certificate 546 | if _, err := Unmarshal(derEncodedSelfSignedCertBytes, &cert); err != nil { 547 | t.Errorf("Unmarshal failed: %v", err) 548 | } 549 | if !reflect.DeepEqual(cert, derEncodedSelfSignedCert) { 550 | t.Errorf("Bad result:\ngot: %+v\nwant: %+v", cert, derEncodedSelfSignedCert) 551 | } 552 | } 553 | 554 | func TestCertificateWithNUL(t *testing.T) { 555 | // This is the paypal NUL-hack certificate. It should fail to parse because 556 | // NUL isn't a permitted character in a PrintableString. 557 | 558 | var cert Certificate 559 | if _, err := Unmarshal(derEncodedPaypalNULCertBytes, &cert); err == nil { 560 | t.Error("Unmarshal succeeded, should not have") 561 | } 562 | } 563 | 564 | type rawStructTest struct { 565 | Raw RawContent 566 | A int 567 | } 568 | 569 | func TestRawStructs(t *testing.T) { 570 | var s rawStructTest 571 | input := []byte{0x30, 0x03, 0x02, 0x01, 0x50} 572 | 573 | rest, err := Unmarshal(input, &s) 574 | if len(rest) != 0 { 575 | t.Errorf("incomplete parse: %x", rest) 576 | return 577 | } 578 | if err != nil { 579 | t.Error(err) 580 | return 581 | } 582 | if s.A != 0x50 { 583 | t.Errorf("bad value for A: got %d want %d", s.A, 0x50) 584 | } 585 | if !bytes.Equal([]byte(s.Raw), input) { 586 | t.Errorf("bad value for Raw: got %x want %x", s.Raw, input) 587 | } 588 | } 589 | 590 | type oiEqualTest struct { 591 | first ObjectIdentifier 592 | second ObjectIdentifier 593 | same bool 594 | } 595 | 596 | var oiEqualTests = []oiEqualTest{ 597 | { 598 | ObjectIdentifier{1, 2, 3}, 599 | ObjectIdentifier{1, 2, 3}, 600 | true, 601 | }, 602 | { 603 | ObjectIdentifier{1}, 604 | ObjectIdentifier{1, 2, 3}, 605 | false, 606 | }, 607 | { 608 | ObjectIdentifier{1, 2, 3}, 609 | ObjectIdentifier{10, 11, 12}, 610 | false, 611 | }, 612 | } 613 | 614 | func TestObjectIdentifierEqual(t *testing.T) { 615 | for _, o := range oiEqualTests { 616 | if s := o.first.Equal(o.second); s != o.same { 617 | t.Errorf("ObjectIdentifier.Equal: got: %t want: %t", s, o.same) 618 | } 619 | } 620 | } 621 | 622 | var derEncodedSelfSignedCert = Certificate{ 623 | TBSCertificate: TBSCertificate{ 624 | Version: 0, 625 | SerialNumber: RawValue{Class: 0, Tag: 2, IsCompound: false, Bytes: []uint8{0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}, FullBytes: []byte{2, 9, 0x0, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 0x98}}, 626 | SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}}, 627 | Issuer: RDNSequence{ 628 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, 629 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, 630 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}}, 631 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}}, 632 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, 633 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, 634 | }, 635 | Validity: Validity{ 636 | NotBefore: time.Date(2009, 10, 8, 00, 25, 53, 0, time.UTC), 637 | NotAfter: time.Date(2010, 10, 8, 00, 25, 53, 0, time.UTC), 638 | }, 639 | Subject: RDNSequence{ 640 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}}, 641 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}}, 642 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 7}, Value: "City"}}, 643 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 10}, Value: "Internet Widgits Pty Ltd"}}, 644 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}}, 645 | RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}}, 646 | }, 647 | PublicKey: PublicKeyInfo{ 648 | Algorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}}, 649 | PublicKey: BitString{ 650 | Bytes: []uint8{ 651 | 0x30, 0x48, 0x2, 0x41, 0x0, 0xcd, 0xb7, 652 | 0x63, 0x9c, 0x32, 0x78, 0xf0, 0x6, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, 653 | 0x90, 0x2b, 0x59, 0x2d, 0x8c, 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, 654 | 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, 655 | 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, 0x96, 0x57, 0x72, 0x2a, 0x4f, 656 | 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, 0xdc, 0x8f, 0xde, 0xec, 657 | 0x35, 0x7d, 0x2, 0x3, 0x1, 0x0, 0x1, 658 | }, 659 | BitLength: 592, 660 | }, 661 | }, 662 | }, 663 | SignatureAlgorithm: AlgorithmIdentifier{Algorithm: ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}}, 664 | SignatureValue: BitString{ 665 | Bytes: []uint8{ 666 | 0xa6, 0x7b, 0x6, 0xec, 0x5e, 0xce, 667 | 0x92, 0x77, 0x2c, 0xa4, 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, 668 | 0x7b, 0x45, 0x11, 0xcd, 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x4, 0x2, 0xdf, 0x2b, 669 | 0x99, 0x8b, 0xb9, 0xa4, 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, 670 | 0xd9, 0x1e, 0xde, 0x14, 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, 671 | 0xfa, 0x88, 0x21, 0x49, 0x4, 0x35, 672 | }, 673 | BitLength: 512, 674 | }, 675 | } 676 | 677 | var derEncodedSelfSignedCertBytes = []byte{ 678 | 0x30, 0x82, 0x02, 0x18, 0x30, 679 | 0x82, 0x01, 0xc2, 0x02, 0x09, 0x00, 0x8c, 0xc3, 0x37, 0x92, 0x10, 0xec, 0x2c, 680 | 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 681 | 0x05, 0x05, 0x00, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 682 | 0x04, 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 683 | 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 684 | 0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, 685 | 0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 686 | 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 687 | 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 688 | 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, 689 | 0x73, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 690 | 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 691 | 0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, 692 | 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 693 | 0x30, 0x39, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, 0x33, 0x5a, 694 | 0x17, 0x0d, 0x31, 0x30, 0x31, 0x30, 0x30, 0x38, 0x30, 0x30, 0x32, 0x35, 0x35, 695 | 0x33, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 696 | 0x06, 0x13, 0x02, 0x58, 0x58, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 697 | 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 698 | 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x04, 0x43, 0x69, 699 | 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 700 | 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 701 | 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x1a, 702 | 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x66, 0x61, 0x6c, 0x73, 703 | 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 704 | 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 705 | 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x40, 0x65, 0x78, 0x61, 706 | 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 707 | 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 708 | 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xcd, 0xb7, 0x63, 0x9c, 0x32, 0x78, 709 | 0xf0, 0x06, 0xaa, 0x27, 0x7f, 0x6e, 0xaf, 0x42, 0x90, 0x2b, 0x59, 0x2d, 0x8c, 710 | 0xbc, 0xbe, 0x38, 0xa1, 0xc9, 0x2b, 0xa4, 0x69, 0x5a, 0x33, 0x1b, 0x1d, 0xea, 711 | 0xde, 0xad, 0xd8, 0xe9, 0xa5, 0xc2, 0x7e, 0x8c, 0x4c, 0x2f, 0xd0, 0xa8, 0x88, 712 | 0x96, 0x57, 0x72, 0x2a, 0x4f, 0x2a, 0xf7, 0x58, 0x9c, 0xf2, 0xc7, 0x70, 0x45, 713 | 0xdc, 0x8f, 0xde, 0xec, 0x35, 0x7d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 714 | 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 715 | 0x03, 0x41, 0x00, 0xa6, 0x7b, 0x06, 0xec, 0x5e, 0xce, 0x92, 0x77, 0x2c, 0xa4, 716 | 0x13, 0xcb, 0xa3, 0xca, 0x12, 0x56, 0x8f, 0xdc, 0x6c, 0x7b, 0x45, 0x11, 0xcd, 717 | 0x40, 0xa7, 0xf6, 0x59, 0x98, 0x04, 0x02, 0xdf, 0x2b, 0x99, 0x8b, 0xb9, 0xa4, 718 | 0xa8, 0xcb, 0xeb, 0x34, 0xc0, 0xf0, 0xa7, 0x8c, 0xf8, 0xd9, 0x1e, 0xde, 0x14, 719 | 0xa5, 0xed, 0x76, 0xbf, 0x11, 0x6f, 0xe3, 0x60, 0xaa, 0xfa, 0x88, 0x21, 0x49, 720 | 0x04, 0x35, 721 | } 722 | 723 | var derEncodedPaypalNULCertBytes = []byte{ 724 | 0x30, 0x82, 0x06, 0x44, 0x30, 725 | 0x82, 0x05, 0xad, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x00, 0xf0, 0x9b, 726 | 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 727 | 0x05, 0x00, 0x30, 0x82, 0x01, 0x12, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 728 | 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 729 | 0x04, 0x08, 0x13, 0x09, 0x42, 0x61, 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, 730 | 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x42, 0x61, 731 | 0x72, 0x63, 0x65, 0x6c, 0x6f, 0x6e, 0x61, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 732 | 0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x50, 0x53, 0x20, 0x43, 0x65, 0x72, 0x74, 733 | 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 734 | 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x73, 0x2e, 0x6c, 0x2e, 0x31, 0x2e, 735 | 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x25, 0x67, 0x65, 0x6e, 0x65, 736 | 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 737 | 0x20, 0x43, 0x2e, 0x49, 0x2e, 0x46, 0x2e, 0x20, 0x20, 0x42, 0x2d, 0x42, 0x36, 738 | 0x32, 0x32, 0x31, 0x30, 0x36, 0x39, 0x35, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 739 | 0x55, 0x04, 0x0b, 0x13, 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, 740 | 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 741 | 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 742 | 0x69, 0x74, 0x79, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 743 | 0x25, 0x69, 0x70, 0x73, 0x43, 0x41, 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 744 | 0x31, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 745 | 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 746 | 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 747 | 0x01, 0x16, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, 0x69, 0x70, 748 | 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x39, 749 | 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, 0x17, 0x0d, 750 | 0x31, 0x31, 0x30, 0x32, 0x32, 0x34, 0x32, 0x33, 0x30, 0x34, 0x31, 0x37, 0x5a, 751 | 0x30, 0x81, 0x94, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 752 | 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 753 | 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 754 | 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x53, 0x61, 0x6e, 0x20, 755 | 0x46, 0x72, 0x61, 0x6e, 0x63, 0x69, 0x73, 0x63, 0x6f, 0x31, 0x11, 0x30, 0x0f, 756 | 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 757 | 0x74, 0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b, 758 | 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x31, 0x2f, 759 | 0x30, 0x2d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x26, 0x77, 0x77, 0x77, 0x2e, 760 | 0x70, 0x61, 0x79, 0x70, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x73, 0x73, 761 | 0x6c, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 762 | 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x63, 0x30, 0x81, 0x9f, 0x30, 0x0d, 763 | 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 764 | 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x69, 765 | 0xfa, 0x6f, 0x3a, 0x00, 0xb4, 0x21, 0x1b, 0xc8, 0xb1, 0x02, 0xd7, 0x3f, 0x19, 766 | 0xb2, 0xc4, 0x6d, 0xb4, 0x54, 0xf8, 0x8b, 0x8a, 0xcc, 0xdb, 0x72, 0xc2, 0x9e, 767 | 0x3c, 0x60, 0xb9, 0xc6, 0x91, 0x3d, 0x82, 0xb7, 0x7d, 0x99, 0xff, 0xd1, 0x29, 768 | 0x84, 0xc1, 0x73, 0x53, 0x9c, 0x82, 0xdd, 0xfc, 0x24, 0x8c, 0x77, 0xd5, 0x41, 769 | 0xf3, 0xe8, 0x1e, 0x42, 0xa1, 0xad, 0x2d, 0x9e, 0xff, 0x5b, 0x10, 0x26, 0xce, 770 | 0x9d, 0x57, 0x17, 0x73, 0x16, 0x23, 0x38, 0xc8, 0xd6, 0xf1, 0xba, 0xa3, 0x96, 771 | 0x5b, 0x16, 0x67, 0x4a, 0x4f, 0x73, 0x97, 0x3a, 0x4d, 0x14, 0xa4, 0xf4, 0xe2, 772 | 0x3f, 0x8b, 0x05, 0x83, 0x42, 0xd1, 0xd0, 0xdc, 0x2f, 0x7a, 0xe5, 0xb6, 0x10, 773 | 0xb2, 0x11, 0xc0, 0xdc, 0x21, 0x2a, 0x90, 0xff, 0xae, 0x97, 0x71, 0x5a, 0x49, 774 | 0x81, 0xac, 0x40, 0xf3, 0x3b, 0xb8, 0x59, 0xb2, 0x4f, 0x02, 0x03, 0x01, 0x00, 775 | 0x01, 0xa3, 0x82, 0x03, 0x21, 0x30, 0x82, 0x03, 0x1d, 0x30, 0x09, 0x06, 0x03, 776 | 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 777 | 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40, 778 | 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03, 0xf8, 779 | 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 780 | 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1d, 0x06, 0x03, 0x55, 781 | 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x61, 0x8f, 0x61, 0x34, 0x43, 0x55, 0x14, 782 | 0x7f, 0x27, 0x09, 0xce, 0x4c, 0x8b, 0xea, 0x9b, 0x7b, 0x19, 0x25, 0xbc, 0x6e, 783 | 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 784 | 0x0e, 0x07, 0x60, 0xd4, 0x39, 0xc9, 0x1b, 0x5b, 0x5d, 0x90, 0x7b, 0x23, 0xc8, 785 | 0xd2, 0x34, 0x9d, 0x4a, 0x9a, 0x46, 0x39, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 786 | 0x11, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x1d, 0x12, 0x04, 787 | 0x15, 0x30, 0x13, 0x81, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x40, 788 | 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x72, 0x06, 0x09, 789 | 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d, 0x04, 0x65, 0x16, 0x63, 790 | 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 791 | 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e, 792 | 0x4f, 0x54, 0x20, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x44, 0x2e, 793 | 0x20, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x20, 0x53, 0x65, 0x72, 0x76, 794 | 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 795 | 0x65, 0x20, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68, 796 | 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 797 | 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x2f, 0x06, 0x09, 0x60, 798 | 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x02, 0x04, 0x22, 0x16, 0x20, 0x68, 799 | 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 800 | 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 801 | 0x32, 0x30, 0x30, 0x32, 0x2f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 802 | 0x86, 0xf8, 0x42, 0x01, 0x04, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 803 | 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 804 | 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 805 | 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, 806 | 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x46, 0x06, 0x09, 807 | 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x03, 0x04, 0x39, 0x16, 0x37, 808 | 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 809 | 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 810 | 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, 811 | 0x69, 0x6f, 0x6e, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, 812 | 0x6d, 0x6c, 0x3f, 0x30, 0x43, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 813 | 0x42, 0x01, 0x07, 0x04, 0x36, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 814 | 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 815 | 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 816 | 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 817 | 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x30, 0x41, 0x06, 0x09, 0x60, 0x86, 818 | 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08, 0x04, 0x34, 0x16, 0x32, 0x68, 0x74, 819 | 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x70, 0x73, 820 | 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 821 | 0x30, 0x30, 0x32, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x4c, 0x41, 822 | 0x53, 0x45, 0x41, 0x31, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x30, 0x81, 0x83, 0x06, 823 | 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x7c, 0x30, 0x7a, 0x30, 0x39, 0xa0, 0x37, 0xa0, 824 | 0x35, 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 825 | 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 826 | 0x73, 0x63, 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 827 | 0x32, 0x30, 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 828 | 0x72, 0x6c, 0x30, 0x3d, 0xa0, 0x3b, 0xa0, 0x39, 0x86, 0x37, 0x68, 0x74, 0x74, 829 | 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x69, 830 | 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x69, 0x70, 0x73, 0x63, 831 | 0x61, 0x32, 0x30, 0x30, 0x32, 0x2f, 0x69, 0x70, 0x73, 0x63, 0x61, 0x32, 0x30, 832 | 0x30, 0x32, 0x43, 0x4c, 0x41, 0x53, 0x45, 0x41, 0x31, 0x2e, 0x63, 0x72, 0x6c, 833 | 0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 834 | 0x26, 0x30, 0x24, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 835 | 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 836 | 0x73, 0x70, 0x2e, 0x69, 0x70, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 837 | 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 838 | 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x68, 0xee, 0x79, 0x97, 0x97, 0xdd, 0x3b, 839 | 0xef, 0x16, 0x6a, 0x06, 0xf2, 0x14, 0x9a, 0x6e, 0xcd, 0x9e, 0x12, 0xf7, 0xaa, 840 | 0x83, 0x10, 0xbd, 0xd1, 0x7c, 0x98, 0xfa, 0xc7, 0xae, 0xd4, 0x0e, 0x2c, 0x9e, 841 | 0x38, 0x05, 0x9d, 0x52, 0x60, 0xa9, 0x99, 0x0a, 0x81, 0xb4, 0x98, 0x90, 0x1d, 842 | 0xae, 0xbb, 0x4a, 0xd7, 0xb9, 0xdc, 0x88, 0x9e, 0x37, 0x78, 0x41, 0x5b, 0xf7, 843 | 0x82, 0xa5, 0xf2, 0xba, 0x41, 0x25, 0x5a, 0x90, 0x1a, 0x1e, 0x45, 0x38, 0xa1, 844 | 0x52, 0x58, 0x75, 0x94, 0x26, 0x44, 0xfb, 0x20, 0x07, 0xba, 0x44, 0xcc, 0xe5, 845 | 0x4a, 0x2d, 0x72, 0x3f, 0x98, 0x47, 0xf6, 0x26, 0xdc, 0x05, 0x46, 0x05, 0x07, 846 | 0x63, 0x21, 0xab, 0x46, 0x9b, 0x9c, 0x78, 0xd5, 0x54, 0x5b, 0x3d, 0x0c, 0x1e, 847 | 0xc8, 0x64, 0x8c, 0xb5, 0x50, 0x23, 0x82, 0x6f, 0xdb, 0xb8, 0x22, 0x1c, 0x43, 848 | 0x96, 0x07, 0xa8, 0xbb, 849 | } 850 | 851 | var stringSliceTestData = [][]string{ 852 | {"foo", "bar"}, 853 | {"foo", "\\bar"}, 854 | {"foo", "\"bar\""}, 855 | {"foo", "åäö"}, 856 | } 857 | 858 | func TestStringSlice(t *testing.T) { 859 | for _, test := range stringSliceTestData { 860 | bs, err := Marshal(test) 861 | if err != nil { 862 | t.Error(err) 863 | } 864 | 865 | var res []string 866 | _, err = Unmarshal(bs, &res) 867 | if err != nil { 868 | t.Error(err) 869 | } 870 | 871 | if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", test) { 872 | t.Errorf("incorrect marshal/unmarshal; %v != %v", res, test) 873 | } 874 | } 875 | } 876 | 877 | type explicitTaggedTimeTest struct { 878 | Time time.Time `asn1:"explicit,tag:0"` 879 | } 880 | 881 | var explicitTaggedTimeTestData = []struct { 882 | in []byte 883 | out explicitTaggedTimeTest 884 | }{ 885 | {[]byte{0x30, 0x11, 0xa0, 0xf, 0x17, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'}, 886 | explicitTaggedTimeTest{time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC)}}, 887 | {[]byte{0x30, 0x17, 0xa0, 0xf, 0x18, 0x13, '2', '0', '1', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '+', '0', '6', '0', '7'}, 888 | explicitTaggedTimeTest{time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}}, 889 | } 890 | 891 | func TestExplicitTaggedTime(t *testing.T) { 892 | // Test that a time.Time will match either tagUTCTime or 893 | // tagGeneralizedTime. 894 | for i, test := range explicitTaggedTimeTestData { 895 | var got explicitTaggedTimeTest 896 | _, err := Unmarshal(test.in, &got) 897 | if err != nil { 898 | t.Errorf("Unmarshal failed at index %d %v", i, err) 899 | } 900 | if !got.Time.Equal(test.out.Time) { 901 | t.Errorf("#%d: got %v, want %v", i, got.Time, test.out.Time) 902 | } 903 | } 904 | } 905 | 906 | type implicitTaggedTimeTest struct { 907 | Time time.Time `asn1:"tag:24"` 908 | } 909 | 910 | func TestImplicitTaggedTime(t *testing.T) { 911 | // An implicitly tagged time value, that happens to have an implicit 912 | // tag equal to a GENERALIZEDTIME, should still be parsed as a UTCTime. 913 | // (There's no "timeType" in fieldParameters to determine what type of 914 | // time should be expected when implicitly tagged.) 915 | der := []byte{0x30, 0x0f, 0x80 | 24, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'} 916 | var result implicitTaggedTimeTest 917 | if _, err := Unmarshal(der, &result); err != nil { 918 | t.Fatalf("Error while parsing: %s", err) 919 | } 920 | if expected := time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC); !result.Time.Equal(expected) { 921 | t.Errorf("Wrong result. Got %v, want %v", result.Time, expected) 922 | } 923 | } 924 | 925 | type truncatedExplicitTagTest struct { 926 | Test int `asn1:"explicit,tag:0"` 927 | } 928 | 929 | func TestTruncatedExplicitTag(t *testing.T) { 930 | // This crashed Unmarshal in the past. See #11154. 931 | der := []byte{ 932 | 0x30, // SEQUENCE 933 | 0x02, // two bytes long 934 | 0xa0, // context-specific, tag 0 935 | 0x30, // 48 bytes long 936 | } 937 | 938 | var result truncatedExplicitTagTest 939 | if _, err := Unmarshal(der, &result); err == nil { 940 | t.Error("Unmarshal returned without error") 941 | } 942 | } 943 | 944 | type invalidUTF8Test struct { 945 | Str string `asn1:"utf8"` 946 | } 947 | 948 | func TestUnmarshalInvalidUTF8(t *testing.T) { 949 | data := []byte("0\x05\f\x03a\xc9c") 950 | var result invalidUTF8Test 951 | _, err := Unmarshal(data, &result) 952 | 953 | const expectedSubstring = "UTF" 954 | if err == nil { 955 | t.Fatal("Successfully unmarshaled invalid UTF-8 data") 956 | } else if !strings.Contains(err.Error(), expectedSubstring) { 957 | t.Fatalf("Expected error to mention %q but error was %q", expectedSubstring, err.Error()) 958 | } 959 | } 960 | 961 | func TestMarshalNilValue(t *testing.T) { 962 | nilValueTestData := []interface{}{ 963 | nil, 964 | struct{ v interface{} }{}, 965 | } 966 | for i, test := range nilValueTestData { 967 | if _, err := Marshal(test); err == nil { 968 | t.Fatalf("#%d: successfully marshaled nil value", i) 969 | } 970 | } 971 | } 972 | --------------------------------------------------------------------------------