github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/support_libraries/secret_disclosure_support/secret_disclosure.go (about) 1 // Copyright (c) 2016, Google Inc. 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 secret_disclosure contains functions which create, interpret and verify 16 // secret disclosure directives of the following form: 17 // 'PolicyKey/DelegatorProgram says DelegateProgram can Read/Write/Create/Delete/Own ProtectedObjectId' 18 19 package secret_disclosure 20 21 import ( 22 "bytes" 23 "crypto/x509" 24 "errors" 25 26 "github.com/golang/protobuf/proto" 27 po "github.com/jlmucb/cloudproxy/go/support_libraries/protected_objects" 28 "github.com/jlmucb/cloudproxy/go/tao" 29 "github.com/jlmucb/cloudproxy/go/tao/auth" 30 ) 31 32 const ( 33 SigningContext = "Policy Secret Disclosure Directive Signature" 34 ReadPredicate = "Read" 35 WritePredicate = "Write" 36 CreatePredicate = "Create" 37 DeletePredicate = "Delete" 38 OwnPredicate = "Own" 39 ) 40 41 func ProcessDirectiveAndUpdateGuard(domain *tao.Domain, directive *DirectiveMessage) error { 42 delegator, delegate, pred, pObj, err := VerifySecretDisclosureDirective(domain.Keys, directive) 43 if err != nil { 44 return err 45 } 46 if domain.Guard.IsAuthorized(*delegate, *pred, []string{pObj.String()}) { 47 return nil 48 } 49 if !domain.Guard.IsAuthorized(*delegator, OwnPredicate, []string{pObj.String()}) { 50 return errors.New("speaker of directive is not owner of object") 51 } 52 return domain.Guard.Authorize(*delegate, *pred, []string{pObj.String()}) 53 54 } 55 56 // This function returns a secret disclosure directive signed by key with the statement: 57 // 'delegator says delegate predicate protectedObjectId'. 58 func CreateSecretDisclosureDirective(key *tao.Keys, delegator, delegate *auth.Prin, 59 predicate string, protectedObjId *po.ObjectIdMessage) (*DirectiveMessage, error) { 60 61 // Construct serialized 'says' statement. 62 serializedObjId, err := proto.Marshal(protectedObjId) 63 if err != nil { 64 return nil, err 65 } 66 pred := auth.MakePredicate(predicate, *delegate, serializedObjId) 67 statement := auth.Says{ 68 Speaker: *delegator, 69 Time: nil, // TODO: For now, time and exp not implemented. 70 Expiration: nil, 71 Message: pred, 72 } 73 serializedStatement := auth.Marshal(statement) 74 75 // Sign serialized statement. 76 signature, err := key.SigningKey.Sign(serializedStatement, SigningContext) 77 if err != nil { 78 return nil, err 79 } 80 81 // Construct and return directive. 82 directive := &DirectiveMessage{ 83 Type: DirectiveMessage_SECRET_DISCLOSURE.Enum(), 84 SerializedStatement: serializedStatement, 85 Signature: signature, 86 Signer: auth.Marshal(key.SigningKey.ToPrincipal()), 87 Cert: key.Cert.Raw, 88 } 89 return directive, nil 90 } 91 92 // This function performs the following checks on a secret disclosure directive. 93 // (1) the directive signature is valid with respect to signerKey of directive 94 // (2) Either 95 // - policyKey matches the signerKey of directive 96 // - directive cert is a valid program cert (signed by policyKey) certifying the signerKey 97 // of directive as belonging to 'delegator' 98 // (3) the directive message is a statement of the form: 99 // 'policyKey/'delegator' says delegate can read protectedObjectId' 100 // where delegate is a Tao Principal and protectedObjectId is a (serialized) protected 101 // object message id. 102 func VerifySecretDisclosureDirective(policyKey *tao.Keys, directive *DirectiveMessage) (*auth.Prin, 103 *auth.Prin, *string, *po.ObjectIdMessage, error) { 104 105 // Check type of directive 106 if directive.Type == nil || *(directive.Type) != DirectiveMessage_SECRET_DISCLOSURE { 107 return nil, nil, nil, nil, errors.New( 108 "secret_disclosure: directive not of secret disclosure type.") 109 } 110 111 var verifier *tao.Verifier 112 var delegatorStr string 113 // Check directive signer matches policy key. 114 if bytes.Compare( 115 auth.Marshal(policyKey.SigningKey.ToPrincipal()), directive.GetSigner()) == 0 { 116 verifier = policyKey.SigningKey.GetVerifierFromSigner() 117 delegatorStr = verifier.ToPrincipal().String() 118 119 } else { 120 // Check if program cert is valid, signed by policy key, 121 // cert public key matches signer and cert name matches speaker 122 // of says statement. 123 cert, err := x509.ParseCertificate(directive.Cert) 124 if err != nil { 125 return nil, nil, nil, nil, errors.New( 126 "error parsing directive program cert") 127 } 128 rootCert := x509.NewCertPool() 129 rootCert.AddCert(policyKey.Cert) 130 verifyOptions := x509.VerifyOptions{Roots: rootCert} 131 _, err = cert.Verify(verifyOptions) 132 if err != nil { 133 return nil, nil, nil, nil, errors.New( 134 "program cert not valid") 135 } 136 verifier, err = tao.VerifierFromX509(cert) 137 delegatorStr = cert.Subject.CommonName 138 if err != nil { 139 return nil, nil, nil, nil, err 140 } 141 if bytes.Compare(auth.Marshal(verifier.ToPrincipal()), directive.GetSigner()) != 0 { 142 return nil, nil, nil, nil, errors.New( 143 "secret_disclosure: directive signer doesn't match program key.") 144 } 145 } 146 147 // Verify signature. 148 ok, err := verifier.Verify(directive.GetSerializedStatement(), SigningContext, 149 directive.GetSignature()) 150 if err != nil { 151 return nil, nil, nil, nil, err 152 } 153 if !ok { 154 return nil, nil, nil, nil, 155 errors.New("secret_disclosure: directive signature check failed.") 156 } 157 158 // Validate and return statement. 159 statement, err := auth.UnmarshalForm(directive.GetSerializedStatement()) 160 if err != nil { 161 return nil, nil, nil, nil, err 162 } 163 var saysStatement *auth.Says 164 if ptr, ok := statement.(*auth.Says); ok { 165 saysStatement = ptr 166 } else if val, ok := statement.(auth.Says); ok { 167 saysStatement = &val 168 } else { 169 return nil, nil, nil, nil, 170 errors.New("secret_disclosure: directive statement not a 'Says'") 171 } 172 stmtSpeaker, ok := saysStatement.Speaker.(auth.Prin) 173 if !ok { 174 return nil, nil, nil, nil, 175 errors.New("secret_disclosure: directive speaker not a 'Prin'") 176 } 177 if stmtSpeaker.String() != delegatorStr { 178 return nil, nil, nil, nil, errors.New( 179 "secret_disclosure: directive statement speaker does not match signer") 180 } 181 pred, ok := saysStatement.Message.(auth.Pred) 182 if !ok { 183 return nil, nil, nil, nil, 184 errors.New("secret_disclosure: directive message not a 'Pred'") 185 } 186 predName := pred.Name 187 if predName == "" { 188 return nil, nil, nil, nil, 189 errors.New("secret_disclosure: directive predicate name is empty") 190 } 191 if len(pred.Arg) != 2 { 192 return nil, nil, nil, nil, 193 errors.New("secret_disclosure: directive predicate doesn't have 2 terms") 194 } 195 delegateName, ok := pred.Arg[0].(auth.Prin) 196 if !ok { 197 return nil, nil, nil, nil, errors.New( 198 "secret_disclosure: directive delegateName Term not of type auth.Prin.") 199 } 200 serializedObjId, ok := pred.Arg[1].(auth.Bytes) 201 if !ok { 202 return nil, nil, nil, nil, errors.New( 203 "secret_disclosure: directive ObjId Term not of type []byte.") 204 } 205 protectedObjId := po.ObjectIdMessage{} 206 err = proto.Unmarshal(serializedObjId, &protectedObjId) 207 if err != nil { 208 return nil, nil, nil, nil, errors.New( 209 "secret_disclosure: error deserializing protected ObjId.") 210 } 211 return &stmtSpeaker, &delegateName, &predName, &protectedObjId, nil 212 }