github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/tao/tao.go (about) 1 // Copyright (c) 2014, Kevin Walsh. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tao 16 17 import ( 18 "fmt" 19 "io" 20 "io/ioutil" 21 "os" 22 "strconv" 23 "strings" 24 "sync" 25 26 "github.com/golang/glog" 27 "github.com/jlmucb/cloudproxy/go/tao/auth" 28 ) 29 30 // Constants used by the Tao implementations for policy, signing contexts, and 31 // environment variables. 32 const ( 33 HostTypeEnvVar = "CLOUDPROXY_TAO_HOST_TYPE" 34 HostSpecEnvVar = "CLOUDPROXY_TAO_HOST_SPEC" 35 HostChannelTypeEnvVar = "CLOUDPROXY_TAO_HOST_CHANNEL_TYPE" 36 HostedTypeEnvVar = "CLOUDPROXY_TAO_HOSTED_TYPE" 37 38 TaoTPMPCRsEnvVar = "CLOUDPROXY_TAO_TPM_PCRS" 39 TaoTPMAIKEnvVar = "CLOUDPROXY_TAO_TPM_AIK" 40 TaoTPMDeviceEnvVar = "CLOUDPROXY_TAO_TPM_DEVICE" 41 42 SharedSecretPolicyDefault = "self" 43 SharedSecretPolicyConservative = "few" 44 SharedSecretPolicyLiberal = "any" 45 46 SealPolicyDefault = "self" 47 SealPolicyConservative = "few" 48 SealPolicyLiberal = "any" 49 50 AttestationSigningContext = "Tao Attestation Signing Context V1" 51 ) 52 53 // Tao is the fundamental Trustworthy Computing interface provided by a host to 54 // its hosted programs. Each level of a system can act as a host by exporting 55 // the Tao interface and providing Tao services to higher-level hosted programs. 56 // 57 // In most cases, a hosted program will use a stub Tao that performs RPC over a 58 // channel to its host. The details of such RPC depend on the specific 59 // implementation of the host: some hosted programs may use pipes to communicate 60 // with their host, others may use sockets, etc. 61 type Tao interface { 62 // GetTaoName returns the Tao principal name assigned to the caller. 63 GetTaoName() (name auth.Prin, err error) 64 65 // ExtendTaoName irreversibly extends the Tao principal name of the caller. 66 ExtendTaoName(subprin auth.SubPrin) error 67 68 // GetRandomBytes returns a slice of n random bytes. 69 GetRandomBytes(n int) (bytes []byte, err error) 70 71 // Rand produces an io.Reader for random bytes from this Tao. 72 Rand() io.Reader 73 74 // GetSharedSecret returns a slice of n secret bytes. 75 GetSharedSecret(n int, policy string) (bytes []byte, err error) 76 77 // Attest requests the Tao host sign a statement on behalf of the caller. The 78 // optional issuer, time and expiration will be given default values if nil. 79 // TODO(kwalsh) Maybe create a struct for these optional params? Or use 80 // auth.Says instead (in which time and expiration are optional) with a 81 // bogus Speaker field like key([]) or nil([]) or self, etc. 82 Attest(issuer *auth.Prin, time, expiration *int64, message auth.Form) (*Attestation, error) 83 84 // Seal encrypts data so only certain hosted programs can unseal it. 85 Seal(data []byte, policy string) (sealed []byte, err error) 86 87 // Unseal decrypts data that has been sealed by the Seal() operation, but only 88 // if the policy specified during the Seal() operation is satisfied. 89 Unseal(sealed []byte) (data []byte, policy string, err error) 90 91 // InitCounter initializes a counter with given label. 92 InitCounter(label string, c int64) error 93 94 // GetCounter retrieves a counter with given label. 95 GetCounter(label string) (int64, error) 96 97 // RollbackProtectedSeal encrypts data under rollback protection 98 // so only certain hosted programs can unseal it. 99 RollbackProtectedSeal(label string, data []byte, policy string) ([]byte, error) 100 101 // RollbackProtectedUnseal decrypts data under rollback protection. 102 RollbackProtectedUnseal(sealed []byte) ([]byte, string, error) 103 } 104 105 // Crypto Suite 106 // Each Library is associated with exactly one cipher suite that describes 107 // seal/unseal, hmac, public key and key derivation algorithms. The original 108 // default was AES-128-CTR-ECC-P256-SHA-256-HMAC-SHA-256. 109 // 110 // Supported crypto suites 111 // Basic256BitCipherSuite is the USG "Top Secret" suite. See 112 // https://www.iad.gov/iad/programs/iad-initiatives/cnsa-suite.cfm. 113 const ( 114 Basic128BitCipherSuite = "sign:ecdsap256,crypt:aes128-ctr-hmacsha256,derive:hdkf-sha256" 115 Basic192BitCipherSuite = "sign:ecdsap384,crypt:aes256-ctr-hmacsha384,derive:hdkf-sha256" 116 Basic256BitCipherSuite = "sign:ecdsap521,crypt:aes256-ctr-hmacsha512,derive:hdkf-sha256" 117 ) 118 // The following variable, defined in "tao_cipher_suite.go," selects the cipher suite. 119 // var TaoCryptoSuite = Basic128BitCipherSuite 120 121 // The following variables are accessible within the tao package so they can be 122 // accessed by the functions that manage the Tao parent singleton object. 123 124 // cachedHost is a singleton parent Tao instance. 125 var cachedHost Tao 126 127 // cacheOnce protects the creation of the singleton cachedHost. 128 var cacheOnce sync.Once 129 130 // registryLock protects Tao host-channel registry operations. 131 var registryLock sync.RWMutex 132 133 // registry stores methods that create an instance of the Tao for a given name. 134 var registry = map[string]func(string) (Tao, error){} 135 136 // Register adds a Tao-creation function for a given host channel type. 137 func Register(name string, generator func(string) (Tao, error)) { 138 registryLock.Lock() 139 registry[name] = generator 140 registryLock.Unlock() 141 } 142 143 // ParentFromConfig gets a parent Tao given a Config that specifies the Tao 144 // type. 145 func ParentFromConfig(tc Config) Tao { 146 cacheOnce.Do(func() { 147 // Get a default config from the environment. 148 tcEnv := NewConfigFromEnv() 149 150 // The incoming config overrides the environment variables for 151 // any values that are set in it. 152 tcEnv.Merge(tc) 153 154 switch tcEnv.HostChannelType { 155 case "tpm": 156 aikblob, err := ioutil.ReadFile(tcEnv.TPMAIKPath) 157 if err != nil { 158 fmt.Fprintf(os.Stderr, "Couldn't read the aikblob: %s\n", err) 159 glog.Error(err) 160 return 161 } 162 163 var aikCert []byte 164 if tcEnv.TPMAIKCertPath != "" { 165 aikCert, err = ioutil.ReadFile(tcEnv.TPMAIKCertPath) 166 if err != nil { 167 fmt.Fprintf(os.Stderr, "Couldn't read the aik cert: %s\n", err) 168 glog.Error(err) 169 return 170 } 171 } 172 173 taoPCRs := tcEnv.TPMPCRs 174 pcrStr := strings.TrimPrefix(taoPCRs, "PCRs(\"") 175 176 // This index operation will never panic, since strings.Split always 177 // returns at least one entry in the resulting slice. 178 pcrIntList := strings.Split(pcrStr, "\", \"")[0] 179 pcrInts := strings.Split(pcrIntList, ",") 180 pcrs := make([]int, len(pcrInts)) 181 for i, s := range pcrInts { 182 var err error 183 pcrs[i], err = strconv.Atoi(s) 184 if err != nil { 185 fmt.Fprintf(os.Stderr, "Couldn't split the PCRs: %s\n", err) 186 glog.Error(err) 187 return 188 } 189 } 190 191 host, err := NewTPMTao(tcEnv.TPMDevice, aikblob, pcrs, aikCert) 192 if err != nil { 193 fmt.Fprintf(os.Stderr, "Couldn't create a new TPMTao: %s\n", err) 194 glog.Error(err) 195 return 196 } 197 198 cachedHost = host 199 case "tpm2": 200 taoPCRs := tcEnv.TPM2PCRs 201 pcrStr := strings.TrimPrefix(taoPCRs, "PCRs(\"") 202 203 // This index operation will never panic, since strings.Split always 204 // returns at least one entry in the resulting slice. 205 pcrIntList := strings.Split(pcrStr, "\", \"")[0] 206 pcrInts := strings.Split(pcrIntList, ",") 207 pcrs := make([]int, len(pcrInts)) 208 for i, s := range pcrInts { 209 var err error 210 pcrs[i], err = strconv.Atoi(s) 211 if err != nil { 212 fmt.Fprintf(os.Stderr, "Couldn't split the PCRs: %s\n", err) 213 glog.Error(err) 214 return 215 } 216 } 217 218 fmt.Fprintf(os.Stderr, "Info dir is %s\n", tc.TPM2InfoDir) 219 host, err := NewTPM2Tao(tcEnv.TPM2Device, tc.TPM2InfoDir, pcrs) 220 if err != nil { 221 fmt.Fprintf(os.Stderr, "Couldn't create a new TPM2Tao: %s\n", err) 222 glog.Error(err) 223 return 224 } 225 cachedHost = host 226 case "pipe": 227 host, err := DeserializeRPC(tcEnv.HostSpec) 228 if err != nil { 229 glog.Error(err) 230 return 231 } 232 cachedHost = host 233 case "file": 234 host, err := DeserializeFileRPC(tcEnv.HostSpec) 235 if err != nil { 236 glog.Error(err) 237 return 238 } 239 cachedHost = host 240 case "unix": 241 host, err := DeserializeUnixSocketRPC(tcEnv.HostSpec) 242 if err != nil { 243 glog.Error(err) 244 return 245 } 246 cachedHost = host 247 default: 248 // Look in the registry to see if there is a function 249 // that can produce a Tao instance for this host spec 250 // and name. 251 registryLock.RLock() 252 defer registryLock.RUnlock() 253 f := registry[tcEnv.HostChannelType] 254 if f == nil { 255 glog.Errorf("unknown host tao channel type %q", tcEnv.HostChannelType) 256 } 257 258 host, err := f(tcEnv.HostSpec) 259 if err != nil { 260 glog.Error(err) 261 return 262 } 263 cachedHost = host 264 } 265 266 }) 267 268 return cachedHost 269 } 270 271 // Parent returns the interface to the underlying host Tao. It depends on a 272 // specific environment variable being set. On success it memoizes the result 273 // before returning it because there should only ever be a single channel to the 274 // host. On failure, it logs a message using glog and returns nil. 275 // Note: errors are not returned so that, once it is confirmed that Parent 276 // returns a non-nil value, callers can use the function result in an 277 // expression, e.g.: 278 // name, err := tao.Parent().GetTaoName() 279 func Parent() Tao { 280 ParentFromConfig(Config{}) 281 return cachedHost 282 }