blob: c4d10e2ffa327d551c0ec369f090e3c80d7af064 [file] [log] [blame]
Srdjan Petrovic86560d42014-08-01 17:23:15 -07001// +build android
2
Srdjan Petrovice2f5fce2014-08-21 15:07:24 -07003package security
Srdjan Petrovic86560d42014-08-01 17:23:15 -07004
5import (
6 "fmt"
7 "runtime"
8 "time"
9 "unsafe"
10
Srdjan Petrovice2f5fce2014-08-21 15:07:24 -070011 "veyron/jni/runtimes/google/util"
Srdjan Petrovic86560d42014-08-01 17:23:15 -070012 "veyron2/security"
13)
14
15// #cgo LDFLAGS: -ljniwrapper
16// #include "jni_wrapper.h"
17import "C"
18
Srdjan Petrovic86560d42014-08-01 17:23:15 -070019// NewPrivateID creates an instance of security.PrivateID that uses the provided
20// Java PrivateID as its underlying implementation.
21// NOTE: Because CGO creates package-local types and because this method may be
22// invoked from a different package, Java types are passed in an empty interface
23// and then cast into their package local types.
24func NewPrivateID(jEnv, jPrivID interface{}) security.PrivateID {
25 env := (*C.JNIEnv)(unsafe.Pointer(util.PtrValue(jEnv)))
26 jPrivateID := C.jobject(unsafe.Pointer(util.PtrValue(jPrivID)))
27
28 // We cannot cache Java environments as they are only valid in the current
29 // thread. We can, however, cache the Java VM and obtain an environment
30 // from it in whatever thread happens to be running at the time.
31 var jVM *C.JavaVM
32 if status := C.GetJavaVM(env, &jVM); status != 0 {
33 panic("couldn't get Java VM from the (Java) environment")
34 }
35 // Create Go Signer.
36 signer := newSigner(env, jPrivateID)
37 // Reference Java PrivateID; it will be de-referenced when the Go PrivateID
38 // created below is garbage-collected (through the finalizer callback we
39 // setup just below).
40 jPrivateID = C.NewGlobalRef(env, jPrivateID)
41 // Create Go PrivateID.
42 id := &privateID{
43 Signer: signer,
44 jVM: jVM,
45 jPrivateID: jPrivateID,
46 }
47 runtime.SetFinalizer(id, func(id *privateID) {
48 envPtr, freeFunc := util.GetEnv(id.jVM)
49 env := (*C.JNIEnv)(envPtr)
50 defer freeFunc()
51 C.DeleteGlobalRef(env, id.jPrivateID)
52 })
53 return id
54}
55
56type privateID struct {
57 security.Signer
58 jVM *C.JavaVM
59 jPrivateID C.jobject
60}
61
62func (id *privateID) PublicID() security.PublicID {
63 envPtr, freeFunc := util.GetEnv(id.jVM)
64 env := (*C.JNIEnv)(envPtr)
65 defer freeFunc()
66 jPublicID := C.jobject(util.CallObjectMethodOrCatch(env, id.jPrivateID, "publicID", nil, publicIDSign))
67 publicIDPtr := util.CallLongMethodOrCatch(env, jPublicID, "getNativePtr", nil)
68 return (*(*security.PublicID)(util.Ptr(publicIDPtr)))
69}
70
71func (id *privateID) Bless(blessee security.PublicID, blessingName string, duration time.Duration, caveats []security.ServiceCaveat) (security.PublicID, error) {
72 envPtr, freeFunc := util.GetEnv(id.jVM)
73 env := (*C.JNIEnv)(envPtr)
74 defer freeFunc()
75 util.GoRef(&blessee) // Un-refed when the Java blessee object created below is finalized.
76 jBlessee := C.jobject(util.NewObjectOrCatch(env, jPublicIDImplClass, []util.Sign{util.LongSign}, &blessee))
77 jDuration := C.jobject(util.NewObjectOrCatch(env, jDurationClass, []util.Sign{util.LongSign}, int64(duration.Seconds()*1000)))
78 jServiceCaveats := newJavaServiceCaveatArray(env, caveats)
79 sCaveatSign := util.ClassSign("com.veyron2.security.ServiceCaveat")
80 durationSign := util.ClassSign("org.joda.time.Duration")
81 jPublicID, err := util.CallObjectMethod(env, id.jPrivateID, "bless", []util.Sign{publicIDSign, util.StringSign, durationSign, util.ArraySign(sCaveatSign)}, publicIDSign, jBlessee, blessingName, jDuration, jServiceCaveats)
82 if err != nil {
83 return nil, err
84 }
85 publicIDPtr := util.CallLongMethodOrCatch(env, jPublicID, "getNativePtr", nil)
86 return (*(*security.PublicID)(util.Ptr(publicIDPtr))), nil
87}
88
89func (id *privateID) Derive(publicID security.PublicID) (security.PrivateID, error) {
90 envPtr, freeFunc := util.GetEnv(id.jVM)
91 env := (*C.JNIEnv)(envPtr)
92 defer freeFunc()
93 util.GoRef(&publicID) // Un-refed when the Java PublicID object created below is finalized.
94 jPublicID := C.jobject(util.NewObjectOrCatch(env, jPublicIDImplClass, []util.Sign{util.LongSign}, &publicID))
95 privateIDSign := util.ClassSign("com.veyron2.security.PublicID")
96 jPrivateID, err := util.CallObjectMethod(env, id.jPrivateID, "derive", []util.Sign{publicIDSign}, privateIDSign, jPublicID)
97 if err != nil {
98 return nil, err
99 }
100 return NewPrivateID(env, C.jobject(jPrivateID)), nil
101}
102
103func (id *privateID) MintDischarge(caveat security.ThirdPartyCaveat, context security.Context, duration time.Duration, caveats []security.ServiceCaveat) (security.ThirdPartyDischarge, error) {
104 return nil, fmt.Errorf("MintDischarge currently not implemented.")
105}