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

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

    26     26   		explicit CACKeyInstance(PP_Instance instance, pp::Core *core) : pp::Instance(instance) {
    27     27   			std::thread(&CACKeyInstance::pcscNaClInitWrapper, this, core).detach();
    28     28   		}
    29     29   
    30     30   		virtual ~CACKeyInstance() {}
    31     31   
    32     32   		virtual void HandleMessageThread(pp::VarDictionary *message) {
    33         -			int numCertificates, i;
    34         -			struct cackey_certificate *certificates;
           33  +			cackey_chrome_returnType signRet;
           34  +			char *pinPrompt;
           35  +			const char *pin;
           36  +			unsigned char buffer[8192];
           37  +			struct cackey_certificate *certificates, incomingCertificateCACKey;
    35     38   			pp::VarDictionary *reply;
    36     39   			pp::VarArray certificatesPPArray;
    37         -			pp::VarArrayBuffer *certificateContents;
    38         -			pp::Var command, incomingCertificateContents;
           40  +			pp::VarArrayBuffer *certificateContents, *incomingCertificateContents, *incomingData, *outgoingData;
           41  +			pp::Var command;
           42  +			const pp::Var *messageAsVar = NULL, *outgoingDataAsVar = NULL;
           43  +			int numCertificates, i;
           44  +			unsigned long outgoingDataLength;
    39     45   
    40     46   			/*
    41     47   			 * Extract the command
    42     48   			 */
    43     49   			command = message->Get("command");
    44     50   
    45     51   			/*
................................................................................
    68     74   
    69     75   				reply->Set("status", "success");
    70     76   				reply->Set("certificates", certificatesPPArray);
    71     77   			} else if (command.AsString() == "sign") {
    72     78   				if (!message->HasKey("certificate")) {
    73     79   					reply->Set("status", "error");
    74     80   					reply->Set("error", "Certificate not supplied");
    75         -				} else {
    76         -					incomingCertificateContents = message->Get("certificate");
    77         -
           81  +				} else if (!message->HasKey("data")) {
    78     82   					reply->Set("status", "error");
    79         -					reply->Set("error", "This function is not yet implemented");
           83  +					reply->Set("error", "Data not supplied");
           84  +				} else {
           85  +					incomingCertificateContents = new pp::VarArrayBuffer(message->Get("certificate"));
           86  +					incomingData = new pp::VarArrayBuffer(message->Get("data"));
           87  +
           88  +					if (message->HasKey("pin")) {
           89  +						pin = message->Get("pin").AsString().c_str();
           90  +					} else {
           91  +						pin = NULL;
           92  +					}
           93  +
           94  +					incomingCertificateCACKey.certificate = incomingCertificateContents->Map();					
           95  +					incomingCertificateCACKey.certificate_len = incomingCertificateContents->ByteLength();					
           96  +
           97  +					outgoingDataLength = sizeof(buffer);
           98  +
           99  +					signRet = cackey_chrome_signMessage(&incomingCertificateCACKey,
          100  +						incomingData->Map(), incomingData->ByteLength(),
          101  +						buffer, &outgoingDataLength,
          102  +						&pinPrompt, pin
          103  +					);
          104  +
          105  +					incomingCertificateContents->Unmap();
          106  +					incomingData->Unmap();
          107  +
          108  +					delete incomingCertificateContents;
          109  +					delete incomingData;
          110  +
          111  +					switch (signRet) {
          112  +						case CACKEY_CHROME_OK:
          113  +							outgoingData = new pp::VarArrayBuffer(outgoingDataLength);
          114  +
          115  +							memcpy(outgoingData->Map(), buffer, outgoingDataLength);
          116  +
          117  +							outgoingData->Unmap();
          118  +
          119  +							outgoingDataAsVar = new pp::Var(outgoingData->pp_var());
          120  +
          121  +							delete outgoingData;
          122  +
          123  +							reply->Set("status", "success");
          124  +							reply->Set("signedData", outgoingDataAsVar);
          125  +
          126  +							delete outgoingDataAsVar;
          127  +
          128  +							break;
          129  +						case CACKEY_CHROME_ERROR:
          130  +							reply->Set("status", "error");
          131  +							reply->Set("error", "Unable to sign data");
          132  +							break;
          133  +						case CACKEY_CHROME_NEEDLOGIN:
          134  +						case CACKEY_CHROME_NEEDPROTECTEDLOGIN:
          135  +							messageAsVar = new pp::Var(message->pp_var());
          136  +
          137  +							reply->Set("status", "retry");
          138  +							reply->Set("originalrequest", messageAsVar);
          139  +
          140  +							delete messageAsVar;
          141  +
          142  +							break;
          143  +					}
    80    144   				}
    81    145   			} else {
    82    146   				reply->Set("status", "error");
    83    147   				reply->Set("error", "Invalid command");
    84    148   			}
    85    149   
    86    150   			/*

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

   325    325   	}
   326    326   
   327    327   	free(certificates);
   328    328   
   329    329   	return;
   330    330   }
   331    331   
   332         -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) {
          332  +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) {
   333    333   	CK_RV chk_rv;
   334    334   	CK_ULONG numSlots, currSlot;
   335    335   	CK_SLOT_ID_PTR slots;
   336    336   	CK_SLOT_INFO slotInfo;
   337    337   	CK_SESSION_HANDLE hSession;
   338    338   	CK_OBJECT_HANDLE hObject, hKey;
   339    339   	CK_ULONG ulObjectCount;

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

     5      5   extern "C" {
     6      6   #  endif
     7      7   
     8      8   #include <stddef.h>
     9      9   
    10     10   struct cackey_certificate {
    11     11   	size_t certificate_len;
    12         -	unsigned char *certificate;
           12  +	void *certificate;
    13     13   };
    14     14   
    15     15   typedef enum {
    16     16   	CACKEY_CHROME_OK,
    17     17   	CACKEY_CHROME_ERROR,
    18     18   	CACKEY_CHROME_NEEDLOGIN,
    19     19   	CACKEY_CHROME_NEEDPROTECTEDLOGIN
    20     20   } cackey_chrome_returnType;
    21     21   
    22     22   int cackey_chrome_listCertificates(struct cackey_certificate **certificates);
    23     23   void cackey_chrome_freeCertificates(struct cackey_certificate *certificates, int certificatesCount);
    24     24   
    25         -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);
           25  +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);
    26     26   
    27     27   void cackey_chrome_terminate(void);
    28     28   
    29     29   #  ifdef __cplusplus
    30     30   }
    31     31   #  endif
    32     32   
    33     33   #endif

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

    21     21   
    22     22   /*
    23     23    * Communication with the PIN entry window
    24     24    */
    25     25   var pinWindowPINValue = "";
    26     26   var pinWindowPreviousHandle = null;
    27     27   
           28  +/*
           29  + * Messages that may need to be retried after getting a PIN
           30  + */
           31  +var cackeyMessagesToRetry = [];
           32  +
    28     33   /*
    29     34    * Handle a response from the NaCl side regarding certificates available
    30     35    */
    31     36   function cackeyMessageIncomingListCertificates(message, chromeCallback) {
    32     37   	var idx;
    33     38   	var certificates = [];
    34     39   
................................................................................
    98    103   		case "error":
    99    104   			console.error("[cackey] Failed to execute command '" + messageEvent.data.command + "': " + messageEvent.data.error);
   100    105   
   101    106   			chromeCallback();
   102    107   
   103    108   			break;
   104    109   		case "retry":
   105         -			pinWindowPINValue = "";
          110  +			/*
          111  +			 * Add the new request to the queue of events to process when the PIN
          112  +			 * prompt is terminated.
          113  +			 */
          114  +			cackeyMessagesToRetry.push(messageEvent);
   106    115   
   107    116   			if (pinWindowPreviousHandle) {
   108    117   				/*
   109    118   				 * An existing PIN entry is in progress
   110         -				 * Wait for it to complete and tie this request to that one.
          119  +				 * Just add the request to the queue (above) and wait
   111    120   				 */
   112    121   
   113         -				/* XXX:TODO */
          122  +				return;
   114    123   			}
   115    124   
          125  +			/*
          126  +			 * Set the handle to an invalid (but non-null) value until the window
          127  +			 * is created in case we are invoked again soon.
          128  +			 */
          129  +			pinWindowPreviousHandle = "invalid";
          130  +
   116    131   			chrome.app.window.create("pin.html", {
   117    132   				"id": "cackeyPINEntry",
   118    133   				"resizable": false,
   119    134   				"alwaysOnTop": true,
   120    135   				"focused": true,
   121    136   				"visibleOnAllWorkspaces": true,
   122    137   				"innerBounds": {
   123    138   					"width": 350,
   124    139   					"minWidth": 350,
   125    140   					"height": 135,
   126    141   					"minHeight": 135
   127    142   				}
   128    143   			}, function(pinWindow) {
          144  +				/*
          145  +				 * Set the PIN value to blank
          146  +				 */
          147  +				pinWindowPINValue = "";
          148  +
   129    149   				if (!pinWindow) {
   130    150   					console.log("[cackey] No window was provided for PIN entry, this will not go well.");
   131    151   
   132    152   					return;
   133    153   				}
   134    154   
   135    155   				pinWindowPreviousHandle = pinWindow;
................................................................................
   138    158   				pinWindow.focus();
   139    159   
   140    160   				/*
   141    161   				 * Register a handler to handle the window being closed without
   142    162   				 * having sent anything
   143    163   				 */
   144    164   				pinWindow.onClosed.addListener(function() {
          165  +					var messageIdx;
          166  +
   145    167   					pinWindowPreviousHandle = null;
   146    168   
   147         -					if (pinWindowPINValue == "") {
   148         -						console.log("[cackey] The PIN dialog was closed without resubmitting the request, treating it as a failure");
          169  +					for (messageIdx = 0; messageIdx < cackeyMessagesToRetry.length; messageIdx++) {
          170  +						var tmpMessageEvent;
   149    171   
   150         -						messageEvent.data.status = "error";
   151         -						messageEvent.data.error = "PIN window closed without a PIN being provided";
          172  +						tmpMessageEvent = cackeyMessagesToRetry[messageIdx];
   152    173   
   153         -						cackeyMessageIncoming(messageEvent);
          174  +						if (pinWindowPINValue == "") {
          175  +							console.log("[cackey] The PIN dialog was closed without gathering a PIN, treating it as a failure.");
          176  +
          177  +							tmpMessageEvent.data.status = "error";
          178  +							tmpMessageEvent.data.error = "PIN window closed without a PIN being provided";
          179  +
          180  +							cackeyMessageIncoming(tmpMessageEvent);
          181  +						} else {
          182  +							cackeyHandle.postMessage(tmpMessageEvent.data.originalrequest);
          183  +						}
          184  +
          185  +						delete cackeyMessagesToRetry[messageIdx];
   154    186   					}
   155    187   
   156    188   					return;
   157    189   				})
   158    190   
   159    191   				/*
   160    192   				 * Pass this message off to the other window so that it may resubmit the request.