func MakeTPMPrin(verifier *rsa.PublicKey, pcrNums []int, pcrVals [][]byte) (auth.Prin, error) { aik, err := x509.MarshalPKIXPublicKey(verifier) if err != nil { return auth.Prin{}, err } name := auth.Prin{ Type: "tpm", Key: auth.Bytes(aik), } asp := auth.PrinExt{ Name: "PCRs", Arg: make([]auth.Term, 2), } var pcrNumStrs []string for _, v := range pcrNums { pcrNumStrs = append(pcrNumStrs, strconv.Itoa(v)) } asp.Arg[0] = auth.Str(strings.Join(pcrNumStrs, ",")) var pcrValStrs []string for _, p := range pcrVals { pcrValStrs = append(pcrValStrs, hex.EncodeToString(p)) } asp.Arg[1] = auth.Str(strings.Join(pcrValStrs, ",")) // The PCRs are the first extension of the name. name.Ext = []auth.PrinExt{asp} return name, nil }
// TruncateAttestation cuts off a delegation chain at its "Program" subprincipal // extension and replaces its prefix with the given key principal. It also // returns the PrinExt that represents exactly the program hash. func TruncateAttestation(kprin auth.Prin, a *Attestation) (auth.Says, auth.PrinExt, error) { // This attestation must have a top-level delegation to a key. Return an // authorization for this program rooted in the policy key. I don't like // this, since it seems like it's much riskier, since this doesn't say // anything about the context in which the program is running. Fortunately, // local policy rules: if a peer won't accept this cert, then the other // program will have to fall back on the longer attestation. stmt, err := auth.UnmarshalForm(a.SerializedStatement) if err != nil { return auth.Says{}, auth.PrinExt{}, err } says, ok := stmt.(auth.Says) if !ok { return auth.Says{}, auth.PrinExt{}, fmt.Errorf("the serialized statement must be a says") } // Replace the message with one that uses the new principal, taking the last // Program subprinicpal, and all its following elements. It should say: // policyKey.Program(...)... says key(...) speaksfor // policyKey.Program(...)..., signed policyKey. sf, ok := says.Message.(auth.Speaksfor) if !ok { return auth.Says{}, auth.PrinExt{}, fmt.Errorf("the message in the statement must be a speaksfor") } delegator, ok := sf.Delegator.(auth.Prin) if !ok { return auth.Says{}, auth.PrinExt{}, fmt.Errorf("the delegator must be a principal") } var prog auth.PrinExt found := false for _, sprin := range delegator.Ext { if !found && (sprin.Name == "Program") { found = true prog = sprin } if found { kprin.Ext = append(kprin.Ext, sprin) } } // TODO(tmroeder): make sure that the delegate is a key and is not, e.g., // the policy key. truncSpeaksfor := auth.Speaksfor{ Delegate: sf.Delegate, Delegator: kprin, } truncSays := auth.Says{ Speaker: kprin, Time: says.Time, Expiration: says.Expiration, Message: truncSpeaksfor, } return truncSays, prog, nil }
func (m *idMap) add(prin auth.Prin) string { // Pick ids for the base principal name, i.e. the tao host // key(...) --> keyi // tpm(...) --> tpmi // Pick ids for all the subprincipal names // Prog(...) --> Programi // etc. p := prin.String() if s, ok := m.ids[p]; ok { return s } ext := prin.Ext prin.Ext = nil s := m.pick(template.HTMLEscapeString(prin.Type), prin.String()) for _, e := range ext { s += "." + m.pick(e.Name, e.String()) } tag := `<span class="id">[ %s ]<span class="pop"><span class="prin">%s</span></span></span>` m.ids[p] = fmt.Sprintf(tag, s, template.HTMLEscapeString(p)) return m.ids[p] }