Add google sign-in demo that yields default blessings

The swift project has been refactored to build two different
frameworks: Vanadium & Syncbase. The Syncbase will yield simple APIs
for a drop-in framework that masquerades much of the V23 stack.

The demo project has improved to have a picker UI, app icon & more.
It has gained an additional demo that uses the Google SignIn SDK to
obtain an oauth token, and then use that token to receive a default
blessing from dev.v.io. Currently it is using a non-Google app
setting but this can be easily swapped out in the future.

Currently private/public keys are asking V23 to store them in a
special directory under Application Support with
NSFileProtectionCompleteUntilUnlock, but in the future this will
change to keep the private key in the Apple Keychain and have
configurable security setting. Unfortunately, the environmental flags
are being read in at boot in the CGO library so we aren’t able to
pass the correct directory until the credentials flag has already been
created and loaded.

The project is also putting Alamofire and Google Sign In under the
third-party repo, but in the (short) future we’ll move to a Cocoapods
setup so we don’t have to directly check in this code.

MultiPart: 1/3
Change-Id: Iabd944391de7fe386449b100cd569b4b1fa26288
diff --git a/impl/google/rpc/swift.go b/impl/google/rpc/swift.go
index 6b5cd8f..476878f 100644
--- a/impl/google/rpc/swift.go
+++ b/impl/google/rpc/swift.go
@@ -155,7 +155,7 @@
 		C.memcpy(cVomResultCopy, unsafe.Pointer(&vomResult[0]), C.size_t(len(vomResult)))
 		var cVomResult C.SwiftByteArray
 		cVomResult.length = C._GoUint64(len(vomResult))
-		cVomResult.data = (*C.char)(cVomResultCopy)
+		cVomResult.data = cVomResultCopy
 		vomResults[i] = cVomResult
 	}
 	return cVomResults, nil
diff --git a/swift.go b/swift.go
index a2fc2e7..2407db7 100644
--- a/swift.go
+++ b/swift.go
@@ -7,13 +7,13 @@
 package swift
 
 import (
+	"os"
 	"unsafe"
 
 	"v.io/x/lib/vlog"
-
+	"v.io/x/ref"
 	// TODO Make this pluggable somehow
 	_ "v.io/x/ref/runtime/factories/roaming"
-
 	sgoogle "v.io/x/swift/impl/google"
 	sutil "v.io/x/swift/util"
 	sv23 "v.io/x/swift/v23"
@@ -23,11 +23,15 @@
 import "C"
 
 //export swift_io_v_v23_V_nativeInitGlobal
-func swift_io_v_v23_V_nativeInitGlobal(errOut *C.SwiftVError) {
+func swift_io_v_v23_V_nativeInitGlobal(credentialsDir *C.char, errOut *C.SwiftVError) {
 	// Send all vlog logs to stderr during the init so that we don't crash on android trying
 	// to create a log file.  These settings will be overwritten in nativeInitLogging below.
 	vlog.Log.Configure(vlog.OverridePriorConfiguration(true), vlog.LogToStderr(true))
 
+	if credentialsDir != nil {
+		dir := C.GoString(credentialsDir)
+		os.Setenv(ref.EnvCredentials, dir)
+	}
 	if err := sv23.Init(); err != nil {
 		sutil.ThrowSwiftError(nil, err, unsafe.Pointer(errOut))
 		return
diff --git a/types.h b/types.h
index 710c46a..622697d 100644
--- a/types.h
+++ b/types.h
@@ -23,7 +23,7 @@
 // Express byte arrays with lengths
 typedef struct {
     _GoUint64 length;
-    char* data;
+    void* data;
 } SwiftByteArray;
 
 // Express arrays of byte arrays with lengths
diff --git a/util/type.go b/util/type.go
index 4f9e919..63457c4 100644
--- a/util/type.go
+++ b/util/type.go
@@ -7,11 +7,18 @@
 package util
 
 import (
+	"encoding/base64"
 	"math"
 	"time"
+	"unsafe"
+
+	"v.io/x/lib/vlog"
 )
 
-// #import "../types.h"
+/*
+#include <stdlib.h>
+#import "../types.h"
+*/
 import "C"
 
 // Useful when needing to return SOMETHING for a given function that otherwise is throwing an error via the errPtr
@@ -22,6 +29,23 @@
 	return empty
 }
 
+func GoBytesCopy(swiftByteArrayPtr unsafe.Pointer) []byte {
+	swiftArray := *(*C.SwiftByteArray)(swiftByteArrayPtr)
+	length := C.int(swiftArray.length)
+	return C.GoBytes(swiftArray.data, length)
+}
+
+func GoBytesNoCopy(swiftByteArrayPtr unsafe.Pointer) []byte {
+	// Taken from https://github.com/golang/go/wiki/cgo
+	// "To create a Go slice backed by a C array (without copying the original data),
+	// one needs to acquire this length at runtime and use a type conversion to a pointer
+	// to a very big array and then slice it to the length that you want"
+	swiftArray := *(*C.SwiftByteArray)(swiftByteArrayPtr)
+	length := int(swiftArray.length)
+	var bytes []byte = (*[1 << 30]byte)(unsafe.Pointer(swiftArray.data))[:length:length]
+	return bytes
+}
+
 // Utils to convert between Go times and durations and NSTimeInterval in Swift
 func NSTimeInterval(t time.Time) C.double {
 	return C.double(t.UnixNano() / 1000000000.0)
@@ -36,3 +60,26 @@
 func GoDuration(d float64) time.Duration {
 	return time.Duration(int64(d * 1e9))
 }
+
+//export swift_io_v_swift_impl_util_type_nativeBase64UrlDecode
+func swift_io_v_swift_impl_util_type_nativeBase64UrlDecode(base64UrlEncoded *C.char) C.SwiftByteArray {
+	// Decode the base64 url encoded string to bytes in a way that prevents extra copies along the CGO boundary.
+	urlEncoded := C.GoString(base64UrlEncoded)
+	maxLength := base64.URLEncoding.DecodedLen(len(urlEncoded))
+	bytesBacking := C.malloc(C.size_t(maxLength))
+	if bytesBacking == nil {
+		vlog.Errorf("Unable allocate %v bytes", maxLength)
+		return EmptySwiftByteArray()
+	}
+	var bytes []byte = (*[1 << 30]byte)(unsafe.Pointer(bytesBacking))[:maxLength:maxLength]
+	n, err := base64.URLEncoding.Decode(bytes, []byte(urlEncoded))
+	if err != nil {
+		vlog.Errorf("Unable to base64 decode string: %v\n", err)
+		C.free(bytesBacking)
+		return EmptySwiftByteArray()
+	}
+	var swiftArray C.SwiftByteArray
+	swiftArray.length = C._GoUint64(n)
+	swiftArray.data = bytesBacking
+	return swiftArray
+}
diff --git a/v23/security/swift.go b/v23/security/swift.go
new file mode 100644
index 0000000..842ed6c
--- /dev/null
+++ b/v23/security/swift.go
@@ -0,0 +1,62 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin,ios
+
+// Package security implements the security API surrounding principals and blessings
+package security
+
+import (
+	"encoding/base64"
+	"fmt"
+	"unsafe"
+
+	"v.io/v23"
+	"v.io/v23/security"
+	"v.io/v23/vom"
+	"v.io/x/swift/util"
+	"v.io/x/swift/v23/context"
+)
+
+/*
+#include <string.h> // memcpy
+#import "../../types.h"
+*/
+import "C"
+
+//export swift_io_v_v23_security_simple_nativeGetPublicKey
+func swift_io_v_v23_security_simple_nativeGetPublicKey(ctxHandle C.GoContextHandle, errOut *C.SwiftVError) *C.char {
+	ctx := context.GoContext(uint64(ctxHandle))
+	der, err := v23.GetPrincipal(ctx).PublicKey().MarshalBinary()
+	if err != nil {
+		util.ThrowSwiftError(nil, err, unsafe.Pointer(errOut))
+		return nil
+	}
+	// Swift will have to free the allocation
+	return C.CString(base64.URLEncoding.EncodeToString(der))
+}
+
+//export swift_io_v_v23_security_simple_nativeSetDefaultBlessings
+func swift_io_v_v23_security_simple_nativeSetDefaultBlessings(ctxHandle C.GoContextHandle, encodedSwiftBlessings C.SwiftByteArray, errOut *C.SwiftVError) {
+	ctx := context.GoContext(uint64(ctxHandle))
+	encodedBlessings := util.GoBytesNoCopy(unsafe.Pointer(&encodedSwiftBlessings))
+	var blessings security.Blessings
+	if err := vom.Decode(encodedBlessings, &blessings); err != nil {
+		ctx.Error("Unable to decode:", err)
+		util.ThrowSwiftError(nil, err, unsafe.Pointer(errOut))
+		return
+	}
+	principal := v23.GetPrincipal(ctx)
+	if err := principal.BlessingStore().SetDefault(blessings); err != nil {
+		util.ThrowSwiftError(nil, err, unsafe.Pointer(errOut))
+		return
+	}
+}
+
+//export swift_io_v_v23_security_simple_nativeGetDefaultBlessingsDebugString
+func swift_io_v_v23_security_simple_nativeGetDefaultBlessingsDebugString(ctxHandle C.GoContextHandle) *C.char {
+	ctx := context.GoContext(uint64(ctxHandle))
+	blessings, _ := v23.GetPrincipal(ctx).BlessingStore().Default()
+	return C.CString(fmt.Sprintf("%v", blessings))
+}
diff --git a/v23/swift.go b/v23/swift.go
index 6100440..201603f 100644
--- a/v23/swift.go
+++ b/v23/swift.go
@@ -8,6 +8,7 @@
 
 import (
 	_ "v.io/x/swift/v23/context"
+	_ "v.io/x/swift/v23/security"
 )
 
 import "C"