Check-in [a90efdf98f]
Overview
Comment:ChromeOS: Start trying to sign data or send it back as needing a PIN or unsignable
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a90efdf98ff7934cc732721377abf57ddd462bb9
User & Date: rkeene on 2016-02-15 06:16:22
Other Links: manifest | tags
Context
2016-02-15
06:17
ChromeOS: Add new PIN to requests to sign once we gathered a new PIN check-in: ae9cfddbd2 user: rkeene tags: trunk
06:16
ChromeOS: Start trying to sign data or send it back as needing a PIN or unsignable check-in: a90efdf98f user: rkeene tags: trunk
05:16
ChromeOS: Converted callback storage from an array to a hash, since we don't care about ordering check-in: a655f43d3b user: rkeene tags: trunk
Changes

Modified build/chrome/cackey-chrome-init.cc from [3317412933] to [039bbe7def].

26
27
28
29
30
31
32

33


34
35
36
37
38



39
40
41
42
43
44
45
		explicit CACKeyInstance(PP_Instance instance, pp::Core *core) : pp::Instance(instance) {
			std::thread(&CACKeyInstance::pcscNaClInitWrapper, this, core).detach();
		}

		virtual ~CACKeyInstance() {}

		virtual void HandleMessageThread(pp::VarDictionary *message) {

			int numCertificates, i;


			struct cackey_certificate *certificates;
			pp::VarDictionary *reply;
			pp::VarArray certificatesPPArray;
			pp::VarArrayBuffer *certificateContents;
			pp::Var command, incomingCertificateContents;




			/*
			 * Extract the command
			 */
			command = message->Get("command");

			/*







>
|
>
>
|


|
|
>
>
>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
		explicit CACKeyInstance(PP_Instance instance, pp::Core *core) : pp::Instance(instance) {
			std::thread(&CACKeyInstance::pcscNaClInitWrapper, this, core).detach();
		}

		virtual ~CACKeyInstance() {}

		virtual void HandleMessageThread(pp::VarDictionary *message) {
			cackey_chrome_returnType signRet;
			char *pinPrompt;
			const char *pin;
			unsigned char buffer[8192];
			struct cackey_certificate *certificates, incomingCertificateCACKey;
			pp::VarDictionary *reply;
			pp::VarArray certificatesPPArray;
			pp::VarArrayBuffer *certificateContents, *incomingCertificateContents, *incomingData, *outgoingData;
			pp::Var command;
			const pp::Var *messageAsVar = NULL, *outgoingDataAsVar = NULL;
			int numCertificates, i;
			unsigned long outgoingDataLength;

			/*
			 * Extract the command
			 */
			command = message->Get("command");

			/*
68
69
70
71
72
73
74



75




















76

77






















78
79












80
81
82
83
84
85
86

				reply->Set("status", "success");
				reply->Set("certificates", certificatesPPArray);
			} else if (command.AsString() == "sign") {
				if (!message->HasKey("certificate")) {
					reply->Set("status", "error");
					reply->Set("error", "Certificate not supplied");



				} else {




















					incomingCertificateContents = message->Get("certificate");
























					reply->Set("status", "error");
					reply->Set("error", "This function is not yet implemented");












				}
			} else {
				reply->Set("status", "error");
				reply->Set("error", "Invalid command");
			}

			/*







>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

				reply->Set("status", "success");
				reply->Set("certificates", certificatesPPArray);
			} else if (command.AsString() == "sign") {
				if (!message->HasKey("certificate")) {
					reply->Set("status", "error");
					reply->Set("error", "Certificate not supplied");
				} else if (!message->HasKey("data")) {
					reply->Set("status", "error");
					reply->Set("error", "Data not supplied");
				} else {
					incomingCertificateContents = new pp::VarArrayBuffer(message->Get("certificate"));
					incomingData = new pp::VarArrayBuffer(message->Get("data"));

					if (message->HasKey("pin")) {
						pin = message->Get("pin").AsString().c_str();
					} else {
						pin = NULL;
					}

					incomingCertificateCACKey.certificate = incomingCertificateContents->Map();					
					incomingCertificateCACKey.certificate_len = incomingCertificateContents->ByteLength();					

					outgoingDataLength = sizeof(buffer);

					signRet = cackey_chrome_signMessage(&incomingCertificateCACKey,
						incomingData->Map(), incomingData->ByteLength(),
						buffer, &outgoingDataLength,
						&pinPrompt, pin
					);

					incomingCertificateContents->Unmap();
					incomingData->Unmap();

					delete incomingCertificateContents;
					delete incomingData;

					switch (signRet) {
						case CACKEY_CHROME_OK:
							outgoingData = new pp::VarArrayBuffer(outgoingDataLength);

							memcpy(outgoingData->Map(), buffer, outgoingDataLength);

							outgoingData->Unmap();

							outgoingDataAsVar = new pp::Var(outgoingData->pp_var());

							delete outgoingData;

							reply->Set("status", "success");
							reply->Set("signedData", outgoingDataAsVar);

							delete outgoingDataAsVar;

							break;
						case CACKEY_CHROME_ERROR:
							reply->Set("status", "error");
							reply->Set("error", "Unable to sign data");
							break;
						case CACKEY_CHROME_NEEDLOGIN:
						case CACKEY_CHROME_NEEDPROTECTEDLOGIN:
							messageAsVar = new pp::Var(message->pp_var());

							reply->Set("status", "retry");
							reply->Set("originalrequest", messageAsVar);

							delete messageAsVar;

							break;
					}
				}
			} else {
				reply->Set("status", "error");
				reply->Set("error", "Invalid command");
			}

			/*

Modified build/chrome/cackey-chrome.c from [145025308e] to [c7ea100694].

325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
	}

	free(certificates);

	return;
}

cackey_chrome_returnType cackey_chrome_signMessage(struct cackey_certificate *certificate, void *data, unsigned long dataLength, unsigned char *destination, unsigned long *destinationLength, char **pinPrompt, char *pin) {
	CK_RV chk_rv;
	CK_ULONG numSlots, currSlot;
	CK_SLOT_ID_PTR slots;
	CK_SLOT_INFO slotInfo;
	CK_SESSION_HANDLE hSession;
	CK_OBJECT_HANDLE hObject, hKey;
	CK_ULONG ulObjectCount;







|







325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
	}

	free(certificates);

	return;
}

cackey_chrome_returnType cackey_chrome_signMessage(struct cackey_certificate *certificate, void *data, unsigned long dataLength, void *destination, unsigned long *destinationLength, char **pinPrompt, const char *pin) {
	CK_RV chk_rv;
	CK_ULONG numSlots, currSlot;
	CK_SLOT_ID_PTR slots;
	CK_SLOT_INFO slotInfo;
	CK_SESSION_HANDLE hSession;
	CK_OBJECT_HANDLE hObject, hKey;
	CK_ULONG ulObjectCount;

Modified build/chrome/cackey-chrome.h from [9c067c4d11] to [ef61e21c1b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#ifndef CACKEY_CHROME_CACKEY_H
#define CACKEY_CHROME_CACKEY_H 1

#  ifdef __cplusplus
extern "C" {
#  endif

#include <stddef.h>

struct cackey_certificate {
	size_t certificate_len;
	unsigned char *certificate;
};

typedef enum {
	CACKEY_CHROME_OK,
	CACKEY_CHROME_ERROR,
	CACKEY_CHROME_NEEDLOGIN,
	CACKEY_CHROME_NEEDPROTECTEDLOGIN
} cackey_chrome_returnType;

int cackey_chrome_listCertificates(struct cackey_certificate **certificates);
void cackey_chrome_freeCertificates(struct cackey_certificate *certificates, int certificatesCount);

cackey_chrome_returnType cackey_chrome_signMessage(struct cackey_certificate *certificate, void *data, unsigned long dataLength, unsigned char *destination, unsigned long *destinationLength, char **pinPrompt, char *pin);

void cackey_chrome_terminate(void);

#  ifdef __cplusplus
}
#  endif

#endif











|












|








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#ifndef CACKEY_CHROME_CACKEY_H
#define CACKEY_CHROME_CACKEY_H 1

#  ifdef __cplusplus
extern "C" {
#  endif

#include <stddef.h>

struct cackey_certificate {
	size_t certificate_len;
	void *certificate;
};

typedef enum {
	CACKEY_CHROME_OK,
	CACKEY_CHROME_ERROR,
	CACKEY_CHROME_NEEDLOGIN,
	CACKEY_CHROME_NEEDPROTECTEDLOGIN
} cackey_chrome_returnType;

int cackey_chrome_listCertificates(struct cackey_certificate **certificates);
void cackey_chrome_freeCertificates(struct cackey_certificate *certificates, int certificatesCount);

cackey_chrome_returnType cackey_chrome_signMessage(struct cackey_certificate *certificate, void *data, unsigned long dataLength, void *destination, unsigned long *destinationLength, char **pinPrompt, const char *pin);

void cackey_chrome_terminate(void);

#  ifdef __cplusplus
}
#  endif

#endif

Modified build/chrome/cackey.js from [25cd0bb896] to [dece8c3884].

21
22
23
24
25
26
27





28
29
30
31
32
33
34

/*
 * Communication with the PIN entry window
 */
var pinWindowPINValue = "";
var pinWindowPreviousHandle = null;






/*
 * Handle a response from the NaCl side regarding certificates available
 */
function cackeyMessageIncomingListCertificates(message, chromeCallback) {
	var idx;
	var certificates = [];








>
>
>
>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

/*
 * Communication with the PIN entry window
 */
var pinWindowPINValue = "";
var pinWindowPreviousHandle = null;

/*
 * Messages that may need to be retried after getting a PIN
 */
var cackeyMessagesToRetry = [];

/*
 * Handle a response from the NaCl side regarding certificates available
 */
function cackeyMessageIncomingListCertificates(message, chromeCallback) {
	var idx;
	var certificates = [];

98
99
100
101
102
103
104
105





106
107
108
109
110
111
112
113

114
115






116
117
118
119
120
121
122
123
124
125
126
127
128





129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144


145
146





147
148
149
150
151
152
153





154
155
156
157
158
159
160
		case "error":
			console.error("[cackey] Failed to execute command '" + messageEvent.data.command + "': " + messageEvent.data.error);

			chromeCallback();

			break;
		case "retry":
			pinWindowPINValue = "";






			if (pinWindowPreviousHandle) {
				/*
				 * An existing PIN entry is in progress
				 * Wait for it to complete and tie this request to that one.
				 */

				/* XXX:TODO */

			}







			chrome.app.window.create("pin.html", {
				"id": "cackeyPINEntry",
				"resizable": false,
				"alwaysOnTop": true,
				"focused": true,
				"visibleOnAllWorkspaces": true,
				"innerBounds": {
					"width": 350,
					"minWidth": 350,
					"height": 135,
					"minHeight": 135
				}
			}, function(pinWindow) {





				if (!pinWindow) {
					console.log("[cackey] No window was provided for PIN entry, this will not go well.");

					return;
				}

				pinWindowPreviousHandle = pinWindow;

				pinWindow.drawAttention();
				pinWindow.focus();

				/*
				 * Register a handler to handle the window being closed without
				 * having sent anything
				 */
				pinWindow.onClosed.addListener(function() {


					pinWindowPreviousHandle = null;






					if (pinWindowPINValue == "") {
						console.log("[cackey] The PIN dialog was closed without resubmitting the request, treating it as a failure");

						messageEvent.data.status = "error";
						messageEvent.data.error = "PIN window closed without a PIN being provided";

						cackeyMessageIncoming(messageEvent);





					}

					return;
				})

				/*
				 * Pass this message off to the other window so that it may resubmit the request.







<
>
>
>
>
>




|


<
>


>
>
>
>
>
>













>
>
>
>
>
















>
>


>
>
>
>
>
|
|

|
|

|
>
>
>
>
>







103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
		case "error":
			console.error("[cackey] Failed to execute command '" + messageEvent.data.command + "': " + messageEvent.data.error);

			chromeCallback();

			break;
		case "retry":

			/*
			 * Add the new request to the queue of events to process when the PIN
			 * prompt is terminated.
			 */
			cackeyMessagesToRetry.push(messageEvent);

			if (pinWindowPreviousHandle) {
				/*
				 * An existing PIN entry is in progress
				 * Just add the request to the queue (above) and wait
				 */


				return;
			}

			/*
			 * Set the handle to an invalid (but non-null) value until the window
			 * is created in case we are invoked again soon.
			 */
			pinWindowPreviousHandle = "invalid";

			chrome.app.window.create("pin.html", {
				"id": "cackeyPINEntry",
				"resizable": false,
				"alwaysOnTop": true,
				"focused": true,
				"visibleOnAllWorkspaces": true,
				"innerBounds": {
					"width": 350,
					"minWidth": 350,
					"height": 135,
					"minHeight": 135
				}
			}, function(pinWindow) {
				/*
				 * Set the PIN value to blank
				 */
				pinWindowPINValue = "";

				if (!pinWindow) {
					console.log("[cackey] No window was provided for PIN entry, this will not go well.");

					return;
				}

				pinWindowPreviousHandle = pinWindow;

				pinWindow.drawAttention();
				pinWindow.focus();

				/*
				 * Register a handler to handle the window being closed without
				 * having sent anything
				 */
				pinWindow.onClosed.addListener(function() {
					var messageIdx;

					pinWindowPreviousHandle = null;

					for (messageIdx = 0; messageIdx < cackeyMessagesToRetry.length; messageIdx++) {
						var tmpMessageEvent;

						tmpMessageEvent = cackeyMessagesToRetry[messageIdx];

						if (pinWindowPINValue == "") {
							console.log("[cackey] The PIN dialog was closed without gathering a PIN, treating it as a failure.");

							tmpMessageEvent.data.status = "error";
							tmpMessageEvent.data.error = "PIN window closed without a PIN being provided";

							cackeyMessageIncoming(tmpMessageEvent);
						} else {
							cackeyHandle.postMessage(tmpMessageEvent.data.originalrequest);
						}

						delete cackeyMessagesToRetry[messageIdx];
					}

					return;
				})

				/*
				 * Pass this message off to the other window so that it may resubmit the request.