...

Source file src/github.com/miekg/pkcs11/pkcs11.go

Documentation: github.com/miekg/pkcs11

     1  // Copyright 2013 Miek Gieben. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:generate go run const_generate.go
     6  
     7  // Package pkcs11 is a wrapper around the PKCS#11 cryptographic library.
     8  package pkcs11
     9  
    10  // It is *assumed*, that:
    11  //
    12  // * Go's uint size == PKCS11's CK_ULONG size
    13  // * CK_ULONG never overflows an Go int
    14  
    15  /*
    16  #cgo windows CFLAGS: -DPACKED_STRUCTURES
    17  #cgo linux LDFLAGS: -ldl
    18  #cgo darwin LDFLAGS: -ldl
    19  #cgo openbsd LDFLAGS:
    20  #cgo freebsd LDFLAGS: -ldl
    21  
    22  #include <stdlib.h>
    23  #include <stdio.h>
    24  #include <string.h>
    25  #include <unistd.h>
    26  
    27  #include "pkcs11go.h"
    28  
    29  #ifdef _WIN32
    30  #include <windows.h>
    31  
    32  struct ctx {
    33  	HMODULE handle;
    34  	CK_FUNCTION_LIST_PTR sym;
    35  };
    36  
    37  // New initializes a ctx and fills the symbol table.
    38  struct ctx *New(const char *module)
    39  {
    40  	CK_C_GetFunctionList list;
    41  	struct ctx *c = calloc(1, sizeof(struct ctx));
    42  	c->handle = LoadLibrary(module);
    43  	if (c->handle == NULL) {
    44  		free(c);
    45  		return NULL;
    46  	}
    47  	list = (CK_C_GetFunctionList) GetProcAddress(c->handle, "C_GetFunctionList");
    48  	if (list == NULL) {
    49  		free(c);
    50  		return NULL;
    51  	}
    52  	list(&c->sym);
    53  	return c;
    54  }
    55  
    56  // Destroy cleans up a ctx.
    57  void Destroy(struct ctx *c)
    58  {
    59  	if (!c) {
    60  		return;
    61  	}
    62  	free(c);
    63  }
    64  #else
    65  #include <dlfcn.h>
    66  
    67  struct ctx {
    68  	void *handle;
    69  	CK_FUNCTION_LIST_PTR sym;
    70  };
    71  
    72  // New initializes a ctx and fills the symbol table.
    73  struct ctx *New(const char *module)
    74  {
    75  	CK_C_GetFunctionList list;
    76  	struct ctx *c = calloc(1, sizeof(struct ctx));
    77  	c->handle = dlopen(module, RTLD_LAZY);
    78  	if (c->handle == NULL) {
    79  		free(c);
    80  		return NULL;
    81  	}
    82  	list = (CK_C_GetFunctionList) dlsym(c->handle, "C_GetFunctionList");
    83  	if (list == NULL) {
    84  		free(c);
    85  		return NULL;
    86  	}
    87  	list(&c->sym);
    88  	return c;
    89  }
    90  
    91  // Destroy cleans up a ctx.
    92  void Destroy(struct ctx *c)
    93  {
    94  	if (!c) {
    95  		return;
    96  	}
    97  	if (c->handle == NULL) {
    98  		return;
    99  	}
   100  	if (dlclose(c->handle) < 0) {
   101  		return;
   102  	}
   103  	free(c);
   104  }
   105  #endif
   106  
   107  CK_RV Initialize(struct ctx * c)
   108  {
   109  	CK_C_INITIALIZE_ARGS args;
   110  	memset(&args, 0, sizeof(args));
   111  	args.flags = CKF_OS_LOCKING_OK;
   112  	return c->sym->C_Initialize(&args);
   113  }
   114  
   115  CK_RV Finalize(struct ctx * c)
   116  {
   117  	return c->sym->C_Finalize(NULL);
   118  }
   119  
   120  CK_RV GetInfo(struct ctx * c, ckInfoPtr info)
   121  {
   122  	CK_INFO p;
   123  	CK_RV e = c->sym->C_GetInfo(&p);
   124  	if (e != CKR_OK) {
   125  		return e;
   126  	}
   127  	info->cryptokiVersion = p.cryptokiVersion;
   128  	memcpy(info->manufacturerID, p.manufacturerID, sizeof(p.manufacturerID));
   129  	info->flags = p.flags;
   130  	memcpy(info->libraryDescription, p.libraryDescription, sizeof(p.libraryDescription));
   131  	info->libraryVersion = p.libraryVersion;
   132  	return e;
   133  }
   134  
   135  CK_RV GetSlotList(struct ctx * c, CK_BBOOL tokenPresent,
   136  		  CK_ULONG_PTR * slotList, CK_ULONG_PTR ulCount)
   137  {
   138  	CK_RV e = c->sym->C_GetSlotList(tokenPresent, NULL, ulCount);
   139  	if (e != CKR_OK) {
   140  		return e;
   141  	}
   142  	*slotList = calloc(*ulCount, sizeof(CK_SLOT_ID));
   143  	e = c->sym->C_GetSlotList(tokenPresent, *slotList, ulCount);
   144  	return e;
   145  }
   146  
   147  CK_RV GetSlotInfo(struct ctx * c, CK_ULONG slotID, CK_SLOT_INFO_PTR info)
   148  {
   149  	CK_RV e = c->sym->C_GetSlotInfo((CK_SLOT_ID) slotID, info);
   150  	return e;
   151  }
   152  
   153  CK_RV GetTokenInfo(struct ctx * c, CK_ULONG slotID, CK_TOKEN_INFO_PTR info)
   154  {
   155  	CK_RV e = c->sym->C_GetTokenInfo((CK_SLOT_ID) slotID, info);
   156  	return e;
   157  }
   158  
   159  CK_RV GetMechanismList(struct ctx * c, CK_ULONG slotID,
   160  		       CK_ULONG_PTR * mech, CK_ULONG_PTR mechlen)
   161  {
   162  	CK_RV e =
   163  	    c->sym->C_GetMechanismList((CK_SLOT_ID) slotID, NULL, mechlen);
   164  	// Gemaltos PKCS11 implementation returns CKR_BUFFER_TOO_SMALL on a NULL ptr instad of CKR_OK as the spec states.
   165  	if (e != CKR_OK && e != CKR_BUFFER_TOO_SMALL) {
   166  		return e;
   167  	}
   168  	*mech = calloc(*mechlen, sizeof(CK_MECHANISM_TYPE));
   169  	e = c->sym->C_GetMechanismList((CK_SLOT_ID) slotID,
   170  				       (CK_MECHANISM_TYPE_PTR) * mech, mechlen);
   171  	return e;
   172  }
   173  
   174  CK_RV GetMechanismInfo(struct ctx * c, CK_ULONG slotID, CK_MECHANISM_TYPE mech,
   175  		       CK_MECHANISM_INFO_PTR info)
   176  {
   177  	CK_RV e = c->sym->C_GetMechanismInfo((CK_SLOT_ID) slotID, mech, info);
   178  	return e;
   179  }
   180  
   181  CK_RV InitToken(struct ctx * c, CK_ULONG slotID, char *pin, CK_ULONG pinlen,
   182  		char *label)
   183  {
   184  	CK_RV e =
   185  	    c->sym->C_InitToken((CK_SLOT_ID) slotID, (CK_UTF8CHAR_PTR) pin,
   186  				pinlen, (CK_UTF8CHAR_PTR) label);
   187  	return e;
   188  }
   189  
   190  CK_RV InitPIN(struct ctx * c, CK_SESSION_HANDLE sh, char *pin, CK_ULONG pinlen)
   191  {
   192  	CK_RV e = c->sym->C_InitPIN(sh, (CK_UTF8CHAR_PTR) pin, pinlen);
   193  	return e;
   194  }
   195  
   196  CK_RV SetPIN(struct ctx * c, CK_SESSION_HANDLE sh, char *oldpin,
   197  	     CK_ULONG oldpinlen, char *newpin, CK_ULONG newpinlen)
   198  {
   199  	CK_RV e = c->sym->C_SetPIN(sh, (CK_UTF8CHAR_PTR) oldpin, oldpinlen,
   200  				   (CK_UTF8CHAR_PTR) newpin, newpinlen);
   201  	return e;
   202  }
   203  
   204  CK_RV OpenSession(struct ctx * c, CK_ULONG slotID, CK_ULONG flags,
   205  		  CK_SESSION_HANDLE_PTR session)
   206  {
   207  	CK_RV e =
   208  	    c->sym->C_OpenSession((CK_SLOT_ID) slotID, (CK_FLAGS) flags, NULL,
   209  				  NULL, session);
   210  	return e;
   211  }
   212  
   213  CK_RV CloseSession(struct ctx * c, CK_SESSION_HANDLE session)
   214  {
   215  	CK_RV e = c->sym->C_CloseSession(session);
   216  	return e;
   217  }
   218  
   219  CK_RV CloseAllSessions(struct ctx * c, CK_ULONG slotID)
   220  {
   221  	CK_RV e = c->sym->C_CloseAllSessions(slotID);
   222  	return e;
   223  }
   224  
   225  CK_RV GetSessionInfo(struct ctx * c, CK_SESSION_HANDLE session,
   226  		     CK_SESSION_INFO_PTR info)
   227  {
   228  	CK_RV e = c->sym->C_GetSessionInfo(session, info);
   229  	return e;
   230  }
   231  
   232  CK_RV GetOperationState(struct ctx * c, CK_SESSION_HANDLE session,
   233  			CK_BYTE_PTR * state, CK_ULONG_PTR statelen)
   234  {
   235  	CK_RV rv = c->sym->C_GetOperationState(session, NULL, statelen);
   236  	if (rv != CKR_OK) {
   237  		return rv;
   238  	}
   239  	*state = calloc(*statelen, sizeof(CK_BYTE));
   240  	if (*state == NULL) {
   241  		return CKR_HOST_MEMORY;
   242  	}
   243  	rv = c->sym->C_GetOperationState(session, *state, statelen);
   244  	return rv;
   245  }
   246  
   247  CK_RV SetOperationState(struct ctx * c, CK_SESSION_HANDLE session,
   248  			CK_BYTE_PTR state, CK_ULONG statelen,
   249  			CK_OBJECT_HANDLE encryptkey, CK_OBJECT_HANDLE authkey)
   250  {
   251  	return c->sym->C_SetOperationState(session, state, statelen, encryptkey,
   252  					   authkey);
   253  }
   254  
   255  CK_RV Login(struct ctx *c, CK_SESSION_HANDLE session, CK_USER_TYPE userType,
   256  	    char *pin, CK_ULONG pinLen)
   257  {
   258  	if (pinLen == 0) {
   259  		pin = NULL;
   260  	}
   261  	CK_RV e =
   262  	    c->sym->C_Login(session, userType, (CK_UTF8CHAR_PTR) pin, pinLen);
   263  	return e;
   264  }
   265  
   266  CK_RV Logout(struct ctx * c, CK_SESSION_HANDLE session)
   267  {
   268  	CK_RV e = c->sym->C_Logout(session);
   269  	return e;
   270  }
   271  
   272  CK_RV CreateObject(struct ctx * c, CK_SESSION_HANDLE session,
   273  		   CK_ATTRIBUTE_PTR temp, CK_ULONG tempCount,
   274  		   CK_OBJECT_HANDLE_PTR obj)
   275  {
   276  	return c->sym->C_CreateObject(session, temp, tempCount, obj);
   277  }
   278  
   279  CK_RV CopyObject(struct ctx * c, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE o,
   280  		 CK_ATTRIBUTE_PTR temp, CK_ULONG tempCount,
   281  		 CK_OBJECT_HANDLE_PTR obj)
   282  {
   283  	return c->sym->C_CopyObject(session, o, temp, tempCount, obj);
   284  }
   285  
   286  CK_RV DestroyObject(struct ctx * c, CK_SESSION_HANDLE session,
   287  		    CK_OBJECT_HANDLE object)
   288  {
   289  	CK_RV e = c->sym->C_DestroyObject(session, object);
   290  	return e;
   291  }
   292  
   293  CK_RV GetObjectSize(struct ctx * c, CK_SESSION_HANDLE session,
   294  		    CK_OBJECT_HANDLE object, CK_ULONG_PTR size)
   295  {
   296  	CK_RV e = c->sym->C_GetObjectSize(session, object, size);
   297  	return e;
   298  }
   299  
   300  CK_RV GetAttributeValue(struct ctx * c, CK_SESSION_HANDLE session,
   301  			CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR temp,
   302  			CK_ULONG templen)
   303  {
   304  	// Call for the first time, check the returned ulValue in the attributes, then
   305  	// allocate enough space and try again.
   306  	CK_RV e = c->sym->C_GetAttributeValue(session, object, temp, templen);
   307  	if (e != CKR_OK) {
   308  		return e;
   309  	}
   310  	CK_ULONG i;
   311  	for (i = 0; i < templen; i++) {
   312  		if ((CK_LONG) temp[i].ulValueLen == -1) {
   313  			// either access denied or no such object
   314  			continue;
   315  		}
   316  		temp[i].pValue = calloc(temp[i].ulValueLen, sizeof(CK_BYTE));
   317  	}
   318  	return c->sym->C_GetAttributeValue(session, object, temp, templen);
   319  }
   320  
   321  CK_RV SetAttributeValue(struct ctx * c, CK_SESSION_HANDLE session,
   322  			CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR temp,
   323  			CK_ULONG templen)
   324  {
   325  	return c->sym->C_SetAttributeValue(session, object, temp, templen);
   326  }
   327  
   328  CK_RV FindObjectsInit(struct ctx * c, CK_SESSION_HANDLE session,
   329  		      CK_ATTRIBUTE_PTR temp, CK_ULONG tempCount)
   330  {
   331  	return c->sym->C_FindObjectsInit(session, temp, tempCount);
   332  }
   333  
   334  CK_RV FindObjects(struct ctx * c, CK_SESSION_HANDLE session,
   335  		  CK_OBJECT_HANDLE_PTR * obj, CK_ULONG max,
   336  		  CK_ULONG_PTR objCount)
   337  {
   338  	*obj = calloc(max, sizeof(CK_OBJECT_HANDLE));
   339  	CK_RV e = c->sym->C_FindObjects(session, *obj, max, objCount);
   340  	return e;
   341  }
   342  
   343  CK_RV FindObjectsFinal(struct ctx * c, CK_SESSION_HANDLE session)
   344  {
   345  	CK_RV e = c->sym->C_FindObjectsFinal(session);
   346  	return e;
   347  }
   348  
   349  CK_RV EncryptInit(struct ctx * c, CK_SESSION_HANDLE session,
   350  		  CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
   351  {
   352  	return c->sym->C_EncryptInit(session, mechanism, key);
   353  }
   354  
   355  CK_RV Encrypt(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
   356  	      CK_ULONG mlen, CK_BYTE_PTR * enc, CK_ULONG_PTR enclen)
   357  {
   358  	CK_RV rv = c->sym->C_Encrypt(session, message, mlen, NULL, enclen);
   359  	if (rv != CKR_OK) {
   360  		return rv;
   361  	}
   362  	*enc = calloc(*enclen, sizeof(CK_BYTE));
   363  	if (*enc == NULL) {
   364  		return CKR_HOST_MEMORY;
   365  	}
   366  	rv = c->sym->C_Encrypt(session, message, mlen, *enc, enclen);
   367  	return rv;
   368  }
   369  
   370  CK_RV EncryptUpdate(struct ctx * c, CK_SESSION_HANDLE session,
   371  		    CK_BYTE_PTR plain, CK_ULONG plainlen, CK_BYTE_PTR * cipher,
   372  		    CK_ULONG_PTR cipherlen)
   373  {
   374  	CK_RV rv =
   375  	    c->sym->C_EncryptUpdate(session, plain, plainlen, NULL, cipherlen);
   376  	if (rv != CKR_OK) {
   377  		return rv;
   378  	}
   379  	*cipher = calloc(*cipherlen, sizeof(CK_BYTE));
   380  	if (*cipher == NULL) {
   381  		return CKR_HOST_MEMORY;
   382  	}
   383  	rv = c->sym->C_EncryptUpdate(session, plain, plainlen, *cipher,
   384  				     cipherlen);
   385  	return rv;
   386  }
   387  
   388  CK_RV EncryptFinal(struct ctx * c, CK_SESSION_HANDLE session,
   389  		   CK_BYTE_PTR * cipher, CK_ULONG_PTR cipherlen)
   390  {
   391  	CK_RV rv = c->sym->C_EncryptFinal(session, NULL, cipherlen);
   392  	if (rv != CKR_OK) {
   393  		return rv;
   394  	}
   395  	*cipher = calloc(*cipherlen, sizeof(CK_BYTE));
   396  	if (*cipher == NULL) {
   397  		return CKR_HOST_MEMORY;
   398  	}
   399  	rv = c->sym->C_EncryptFinal(session, *cipher, cipherlen);
   400  	return rv;
   401  }
   402  
   403  CK_RV DecryptInit(struct ctx * c, CK_SESSION_HANDLE session,
   404  		  CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
   405  {
   406  	return c->sym->C_DecryptInit(session, mechanism, key);
   407  }
   408  
   409  CK_RV Decrypt(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR cipher,
   410  	      CK_ULONG clen, CK_BYTE_PTR * plain, CK_ULONG_PTR plainlen)
   411  {
   412  	CK_RV e = c->sym->C_Decrypt(session, cipher, clen, NULL, plainlen);
   413  	if (e != CKR_OK) {
   414  		return e;
   415  	}
   416  	*plain = calloc(*plainlen, sizeof(CK_BYTE));
   417  	if (*plain == NULL) {
   418  		return CKR_HOST_MEMORY;
   419  	}
   420  	e = c->sym->C_Decrypt(session, cipher, clen, *plain, plainlen);
   421  	return e;
   422  }
   423  
   424  CK_RV DecryptUpdate(struct ctx * c, CK_SESSION_HANDLE session,
   425  		    CK_BYTE_PTR cipher, CK_ULONG cipherlen, CK_BYTE_PTR * part,
   426  		    CK_ULONG_PTR partlen)
   427  {
   428  	CK_RV rv =
   429  	    c->sym->C_DecryptUpdate(session, cipher, cipherlen, NULL, partlen);
   430  	if (rv != CKR_OK) {
   431  		return rv;
   432  	}
   433  	*part = calloc(*partlen, sizeof(CK_BYTE));
   434  	if (*part == NULL) {
   435  		return CKR_HOST_MEMORY;
   436  	}
   437  	rv = c->sym->C_DecryptUpdate(session, cipher, cipherlen, *part,
   438  				     partlen);
   439  	return rv;
   440  }
   441  
   442  CK_RV DecryptFinal(struct ctx * c, CK_SESSION_HANDLE session,
   443  		   CK_BYTE_PTR * plain, CK_ULONG_PTR plainlen)
   444  {
   445  	CK_RV rv = c->sym->C_DecryptFinal(session, NULL, plainlen);
   446  	if (rv != CKR_OK) {
   447  		return rv;
   448  	}
   449  	*plain = calloc(*plainlen, sizeof(CK_BYTE));
   450  	if (*plain == NULL) {
   451  		return CKR_HOST_MEMORY;
   452  	}
   453  	rv = c->sym->C_DecryptFinal(session, *plain, plainlen);
   454  	return rv;
   455  }
   456  
   457  CK_RV DigestInit(struct ctx * c, CK_SESSION_HANDLE session,
   458  		 CK_MECHANISM_PTR mechanism)
   459  {
   460  	return c->sym->C_DigestInit(session, mechanism);
   461  }
   462  
   463  CK_RV Digest(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
   464  	     CK_ULONG mlen, CK_BYTE_PTR * hash, CK_ULONG_PTR hashlen)
   465  {
   466  	CK_RV rv = c->sym->C_Digest(session, message, mlen, NULL, hashlen);
   467  	if (rv != CKR_OK) {
   468  		return rv;
   469  	}
   470  	*hash = calloc(*hashlen, sizeof(CK_BYTE));
   471  	if (*hash == NULL) {
   472  		return CKR_HOST_MEMORY;
   473  	}
   474  	rv = c->sym->C_Digest(session, message, mlen, *hash, hashlen);
   475  	return rv;
   476  }
   477  
   478  CK_RV DigestUpdate(struct ctx * c, CK_SESSION_HANDLE session,
   479  		   CK_BYTE_PTR message, CK_ULONG mlen)
   480  {
   481  	CK_RV rv = c->sym->C_DigestUpdate(session, message, mlen);
   482  	return rv;
   483  }
   484  
   485  CK_RV DigestKey(struct ctx * c, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key)
   486  {
   487  	CK_RV rv = c->sym->C_DigestKey(session, key);
   488  	return rv;
   489  }
   490  
   491  CK_RV DigestFinal(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR * hash,
   492  		  CK_ULONG_PTR hashlen)
   493  {
   494  	CK_RV rv = c->sym->C_DigestFinal(session, NULL, hashlen);
   495  	if (rv != CKR_OK) {
   496  		return rv;
   497  	}
   498  	*hash = calloc(*hashlen, sizeof(CK_BYTE));
   499  	if (*hash == NULL) {
   500  		return CKR_HOST_MEMORY;
   501  	}
   502  	rv = c->sym->C_DigestFinal(session, *hash, hashlen);
   503  	return rv;
   504  }
   505  
   506  CK_RV SignInit(struct ctx * c, CK_SESSION_HANDLE session,
   507  	       CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
   508  {
   509  	return c->sym->C_SignInit(session, mechanism, key);
   510  }
   511  
   512  CK_RV Sign(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
   513  	   CK_ULONG mlen, CK_BYTE_PTR * sig, CK_ULONG_PTR siglen)
   514  {
   515  	CK_RV rv = c->sym->C_Sign(session, message, mlen, NULL, siglen);
   516  	if (rv != CKR_OK) {
   517  		return rv;
   518  	}
   519  	*sig = calloc(*siglen, sizeof(CK_BYTE));
   520  	if (*sig == NULL) {
   521  		return CKR_HOST_MEMORY;
   522  	}
   523  	rv = c->sym->C_Sign(session, message, mlen, *sig, siglen);
   524  	return rv;
   525  }
   526  
   527  CK_RV SignUpdate(struct ctx * c, CK_SESSION_HANDLE session,
   528  		 CK_BYTE_PTR message, CK_ULONG mlen)
   529  {
   530  	CK_RV rv = c->sym->C_SignUpdate(session, message, mlen);
   531  	return rv;
   532  }
   533  
   534  CK_RV SignFinal(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR * sig,
   535  		CK_ULONG_PTR siglen)
   536  {
   537  	CK_RV rv = c->sym->C_SignFinal(session, NULL, siglen);
   538  	if (rv != CKR_OK) {
   539  		return rv;
   540  	}
   541  	*sig = calloc(*siglen, sizeof(CK_BYTE));
   542  	if (*sig == NULL) {
   543  		return CKR_HOST_MEMORY;
   544  	}
   545  	rv = c->sym->C_SignFinal(session, *sig, siglen);
   546  	return rv;
   547  }
   548  
   549  CK_RV SignRecoverInit(struct ctx * c, CK_SESSION_HANDLE session,
   550  		      CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
   551  {
   552  	return c->sym->C_SignRecoverInit(session, mechanism, key);
   553  }
   554  
   555  CK_RV SignRecover(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR data,
   556  		  CK_ULONG datalen, CK_BYTE_PTR * sig, CK_ULONG_PTR siglen)
   557  {
   558  	CK_RV rv = c->sym->C_SignRecover(session, data, datalen, NULL, siglen);
   559  	if (rv != CKR_OK) {
   560  		return rv;
   561  	}
   562  	*sig = calloc(*siglen, sizeof(CK_BYTE));
   563  	if (*sig == NULL) {
   564  		return CKR_HOST_MEMORY;
   565  	}
   566  	rv = c->sym->C_SignRecover(session, data, datalen, *sig, siglen);
   567  	return rv;
   568  }
   569  
   570  CK_RV VerifyInit(struct ctx * c, CK_SESSION_HANDLE session,
   571  		 CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
   572  {
   573  	return c->sym->C_VerifyInit(session, mechanism, key);
   574  }
   575  
   576  CK_RV Verify(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
   577  	     CK_ULONG mesglen, CK_BYTE_PTR sig, CK_ULONG siglen)
   578  {
   579  	CK_RV rv = c->sym->C_Verify(session, message, mesglen, sig, siglen);
   580  	return rv;
   581  }
   582  
   583  CK_RV VerifyUpdate(struct ctx * c, CK_SESSION_HANDLE session,
   584  		   CK_BYTE_PTR part, CK_ULONG partlen)
   585  {
   586  	CK_RV rv = c->sym->C_VerifyUpdate(session, part, partlen);
   587  	return rv;
   588  }
   589  
   590  CK_RV VerifyFinal(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR sig,
   591  		  CK_ULONG siglen)
   592  {
   593  	CK_RV rv = c->sym->C_VerifyFinal(session, sig, siglen);
   594  	return rv;
   595  }
   596  
   597  CK_RV VerifyRecoverInit(struct ctx * c, CK_SESSION_HANDLE session,
   598  			CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key)
   599  {
   600  	return c->sym->C_VerifyRecoverInit(session, mechanism, key);
   601  }
   602  
   603  CK_RV VerifyRecover(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR sig,
   604  		    CK_ULONG siglen, CK_BYTE_PTR * data, CK_ULONG_PTR datalen)
   605  {
   606  	CK_RV rv = c->sym->C_VerifyRecover(session, sig, siglen, NULL, datalen);
   607  	if (rv != CKR_OK) {
   608  		return rv;
   609  	}
   610  	*data = calloc(*datalen, sizeof(CK_BYTE));
   611  	if (*data == NULL) {
   612  		return CKR_HOST_MEMORY;
   613  	}
   614  	rv = c->sym->C_VerifyRecover(session, sig, siglen, *data, datalen);
   615  	return rv;
   616  }
   617  
   618  CK_RV DigestEncryptUpdate(struct ctx * c, CK_SESSION_HANDLE session,
   619  			  CK_BYTE_PTR part, CK_ULONG partlen, CK_BYTE_PTR * enc,
   620  			  CK_ULONG_PTR enclen)
   621  {
   622  	CK_RV rv =
   623  	    c->sym->C_DigestEncryptUpdate(session, part, partlen, NULL, enclen);
   624  	if (rv != CKR_OK) {
   625  		return rv;
   626  	}
   627  	*enc = calloc(*enclen, sizeof(CK_BYTE));
   628  	if (*enc == NULL) {
   629  		return CKR_HOST_MEMORY;
   630  	}
   631  	rv = c->sym->C_DigestEncryptUpdate(session, part, partlen, *enc,
   632  					   enclen);
   633  	return rv;
   634  }
   635  
   636  CK_RV DecryptDigestUpdate(struct ctx * c, CK_SESSION_HANDLE session,
   637  			  CK_BYTE_PTR cipher, CK_ULONG cipherlen,
   638  			  CK_BYTE_PTR * part, CK_ULONG_PTR partlen)
   639  {
   640  	CK_RV rv =
   641  	    c->sym->C_DecryptDigestUpdate(session, cipher, cipherlen, NULL,
   642  					  partlen);
   643  	if (rv != CKR_OK) {
   644  		return rv;
   645  	}
   646  	*part = calloc(*partlen, sizeof(CK_BYTE));
   647  	if (*part == NULL) {
   648  		return CKR_HOST_MEMORY;
   649  	}
   650  	rv = c->sym->C_DecryptDigestUpdate(session, cipher, cipherlen, *part,
   651  					   partlen);
   652  	return rv;
   653  }
   654  
   655  CK_RV SignEncryptUpdate(struct ctx * c, CK_SESSION_HANDLE session,
   656  			CK_BYTE_PTR part, CK_ULONG partlen, CK_BYTE_PTR * enc,
   657  			CK_ULONG_PTR enclen)
   658  {
   659  	CK_RV rv =
   660  	    c->sym->C_SignEncryptUpdate(session, part, partlen, NULL, enclen);
   661  	if (rv != CKR_OK) {
   662  		return rv;
   663  	}
   664  	*enc = calloc(*enclen, sizeof(CK_BYTE));
   665  	if (*enc == NULL) {
   666  		return CKR_HOST_MEMORY;
   667  	}
   668  	rv = c->sym->C_SignEncryptUpdate(session, part, partlen, *enc, enclen);
   669  	return rv;
   670  }
   671  
   672  CK_RV DecryptVerifyUpdate(struct ctx * c, CK_SESSION_HANDLE session,
   673  			  CK_BYTE_PTR cipher, CK_ULONG cipherlen,
   674  			  CK_BYTE_PTR * part, CK_ULONG_PTR partlen)
   675  {
   676  	CK_RV rv =
   677  	    c->sym->C_DecryptVerifyUpdate(session, cipher, cipherlen, NULL,
   678  					  partlen);
   679  	if (rv != CKR_OK) {
   680  		return rv;
   681  	}
   682  	*part = calloc(*partlen, sizeof(CK_BYTE));
   683  	if (*part == NULL) {
   684  		return CKR_HOST_MEMORY;
   685  	}
   686  	rv = c->sym->C_DecryptVerifyUpdate(session, cipher, cipherlen, *part,
   687  					   partlen);
   688  	return rv;
   689  }
   690  
   691  CK_RV GenerateKey(struct ctx * c, CK_SESSION_HANDLE session,
   692  		  CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR temp,
   693  		  CK_ULONG tempCount, CK_OBJECT_HANDLE_PTR key)
   694  {
   695  	return c->sym->C_GenerateKey(session, mechanism, temp, tempCount, key);
   696  }
   697  
   698  CK_RV GenerateKeyPair(struct ctx * c, CK_SESSION_HANDLE session,
   699  		      CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR pub,
   700  		      CK_ULONG pubCount, CK_ATTRIBUTE_PTR priv,
   701  		      CK_ULONG privCount, CK_OBJECT_HANDLE_PTR pubkey,
   702  		      CK_OBJECT_HANDLE_PTR privkey)
   703  {
   704  	return c->sym->C_GenerateKeyPair(session, mechanism, pub, pubCount,
   705  		priv, privCount, pubkey, privkey);
   706  }
   707  
   708  CK_RV WrapKey(struct ctx * c, CK_SESSION_HANDLE session,
   709  	      CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE wrappingkey,
   710  	      CK_OBJECT_HANDLE key, CK_BYTE_PTR * wrapped,
   711  	      CK_ULONG_PTR wrappedlen)
   712  {
   713  	CK_RV rv = c->sym->C_WrapKey(session, mechanism, wrappingkey, key, NULL,
   714  				     wrappedlen);
   715  	if (rv != CKR_OK) {
   716  		return rv;
   717  	}
   718  	*wrapped = calloc(*wrappedlen, sizeof(CK_BYTE));
   719  	if (*wrapped == NULL) {
   720  		return CKR_HOST_MEMORY;
   721  	}
   722  	rv = c->sym->C_WrapKey(session, mechanism, wrappingkey, key, *wrapped,
   723  			       wrappedlen);
   724  	return rv;
   725  }
   726  
   727  CK_RV DeriveKey(struct ctx * c, CK_SESSION_HANDLE session,
   728  		CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE basekey,
   729  		CK_ATTRIBUTE_PTR a, CK_ULONG alen, CK_OBJECT_HANDLE_PTR key)
   730  {
   731  	return c->sym->C_DeriveKey(session, mechanism, basekey, a, alen, key);
   732  }
   733  
   734  CK_RV UnwrapKey(struct ctx * c, CK_SESSION_HANDLE session,
   735  		CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE unwrappingkey,
   736  		CK_BYTE_PTR wrappedkey, CK_ULONG wrappedkeylen,
   737  		CK_ATTRIBUTE_PTR a, CK_ULONG alen, CK_OBJECT_HANDLE_PTR key)
   738  {
   739  	return c->sym->C_UnwrapKey(session, mechanism, unwrappingkey, wrappedkey,
   740  				      wrappedkeylen, a, alen, key);
   741  }
   742  
   743  CK_RV SeedRandom(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR seed,
   744  		 CK_ULONG seedlen)
   745  {
   746  	CK_RV e = c->sym->C_SeedRandom(session, seed, seedlen);
   747  	return e;
   748  }
   749  
   750  CK_RV GenerateRandom(struct ctx * c, CK_SESSION_HANDLE session,
   751  		     CK_BYTE_PTR * rand, CK_ULONG length)
   752  {
   753  	*rand = calloc(length, sizeof(CK_BYTE));
   754  	if (*rand == NULL) {
   755  		return CKR_HOST_MEMORY;
   756  	}
   757  	CK_RV e = c->sym->C_GenerateRandom(session, *rand, length);
   758  	return e;
   759  }
   760  
   761  CK_RV WaitForSlotEvent(struct ctx * c, CK_FLAGS flags, CK_ULONG_PTR slot)
   762  {
   763  	CK_RV e =
   764  	    c->sym->C_WaitForSlotEvent(flags, (CK_SLOT_ID_PTR) slot, NULL);
   765  	return e;
   766  }
   767  
   768  static inline CK_VOID_PTR getAttributePval(CK_ATTRIBUTE_PTR a)
   769  {
   770  	return a->pValue;
   771  }
   772  
   773  */
   774  import "C"
   775  import (
   776  	"strings"
   777  	"unsafe"
   778  )
   779  
   780  // Ctx contains the current pkcs11 context.
   781  type Ctx struct {
   782  	ctx *C.struct_ctx
   783  }
   784  
   785  // New creates a new context and initializes the module/library for use.
   786  func New(module string) *Ctx {
   787  	c := new(Ctx)
   788  	mod := C.CString(module)
   789  	defer C.free(unsafe.Pointer(mod))
   790  	c.ctx = C.New(mod)
   791  	if c.ctx == nil {
   792  		return nil
   793  	}
   794  	return c
   795  }
   796  
   797  // Destroy unloads the module/library and frees any remaining memory.
   798  func (c *Ctx) Destroy() {
   799  	if c == nil || c.ctx == nil {
   800  		return
   801  	}
   802  	C.Destroy(c.ctx)
   803  	c.ctx = nil
   804  }
   805  
   806  // Initialize initializes the Cryptoki library.
   807  func (c *Ctx) Initialize() error {
   808  	e := C.Initialize(c.ctx)
   809  	return toError(e)
   810  }
   811  
   812  // Finalize indicates that an application is done with the Cryptoki library.
   813  func (c *Ctx) Finalize() error {
   814  	if c.ctx == nil {
   815  		return toError(CKR_CRYPTOKI_NOT_INITIALIZED)
   816  	}
   817  	e := C.Finalize(c.ctx)
   818  	return toError(e)
   819  }
   820  
   821  // GetInfo returns general information about Cryptoki.
   822  func (c *Ctx) GetInfo() (Info, error) {
   823  	var p C.ckInfo
   824  	e := C.GetInfo(c.ctx, &p)
   825  	i := Info{
   826  		CryptokiVersion:    toVersion(p.cryptokiVersion),
   827  		ManufacturerID:     strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&p.manufacturerID[0]), 32)), " "),
   828  		Flags:              uint(p.flags),
   829  		LibraryDescription: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&p.libraryDescription[0]), 32)), " "),
   830  		LibraryVersion:     toVersion(p.libraryVersion),
   831  	}
   832  	return i, toError(e)
   833  }
   834  
   835  // GetSlotList obtains a list of slots in the system.
   836  func (c *Ctx) GetSlotList(tokenPresent bool) ([]uint, error) {
   837  	var (
   838  		slotList C.CK_ULONG_PTR
   839  		ulCount  C.CK_ULONG
   840  	)
   841  	e := C.GetSlotList(c.ctx, cBBool(tokenPresent), &slotList, &ulCount)
   842  	if toError(e) != nil {
   843  		return nil, toError(e)
   844  	}
   845  	l := toList(slotList, ulCount)
   846  	return l, nil
   847  }
   848  
   849  // GetSlotInfo obtains information about a particular slot in the system.
   850  func (c *Ctx) GetSlotInfo(slotID uint) (SlotInfo, error) {
   851  	var csi C.CK_SLOT_INFO
   852  	e := C.GetSlotInfo(c.ctx, C.CK_ULONG(slotID), &csi)
   853  	s := SlotInfo{
   854  		SlotDescription: strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&csi.slotDescription[0]), 64)), " "),
   855  		ManufacturerID:  strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&csi.manufacturerID[0]), 32)), " "),
   856  		Flags:           uint(csi.flags),
   857  		HardwareVersion: toVersion(csi.hardwareVersion),
   858  		FirmwareVersion: toVersion(csi.firmwareVersion),
   859  	}
   860  	return s, toError(e)
   861  }
   862  
   863  // GetTokenInfo obtains information about a particular token
   864  // in the system.
   865  func (c *Ctx) GetTokenInfo(slotID uint) (TokenInfo, error) {
   866  	var cti C.CK_TOKEN_INFO
   867  	e := C.GetTokenInfo(c.ctx, C.CK_ULONG(slotID), &cti)
   868  	s := TokenInfo{
   869  		Label:              strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&cti.label[0]), 32)), " "),
   870  		ManufacturerID:     strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&cti.manufacturerID[0]), 32)), " "),
   871  		Model:              strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&cti.model[0]), 16)), " "),
   872  		SerialNumber:       strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&cti.serialNumber[0]), 16)), " "),
   873  		Flags:              uint(cti.flags),
   874  		MaxSessionCount:    uint(cti.ulMaxSessionCount),
   875  		SessionCount:       uint(cti.ulSessionCount),
   876  		MaxRwSessionCount:  uint(cti.ulMaxRwSessionCount),
   877  		RwSessionCount:     uint(cti.ulRwSessionCount),
   878  		MaxPinLen:          uint(cti.ulMaxPinLen),
   879  		MinPinLen:          uint(cti.ulMinPinLen),
   880  		TotalPublicMemory:  uint(cti.ulTotalPublicMemory),
   881  		FreePublicMemory:   uint(cti.ulFreePublicMemory),
   882  		TotalPrivateMemory: uint(cti.ulTotalPrivateMemory),
   883  		FreePrivateMemory:  uint(cti.ulFreePrivateMemory),
   884  		HardwareVersion:    toVersion(cti.hardwareVersion),
   885  		FirmwareVersion:    toVersion(cti.firmwareVersion),
   886  		UTCTime:            strings.TrimRight(string(C.GoBytes(unsafe.Pointer(&cti.utcTime[0]), 16)), " "),
   887  	}
   888  	return s, toError(e)
   889  }
   890  
   891  // GetMechanismList obtains a list of mechanism types supported by a token.
   892  func (c *Ctx) GetMechanismList(slotID uint) ([]*Mechanism, error) {
   893  	var (
   894  		mech    C.CK_ULONG_PTR // in pkcs#11 we're all CK_ULONGs \o/
   895  		mechlen C.CK_ULONG
   896  	)
   897  	e := C.GetMechanismList(c.ctx, C.CK_ULONG(slotID), &mech, &mechlen)
   898  	if toError(e) != nil {
   899  		return nil, toError(e)
   900  	}
   901  	// Although the function returns only type, cast them back into real
   902  	// attributes as this is used in other functions.
   903  	m := make([]*Mechanism, int(mechlen))
   904  	for i, typ := range toList(mech, mechlen) {
   905  		m[i] = NewMechanism(typ, nil)
   906  	}
   907  	return m, nil
   908  }
   909  
   910  // GetMechanismInfo obtains information about a particular
   911  // mechanism possibly supported by a token.
   912  func (c *Ctx) GetMechanismInfo(slotID uint, m []*Mechanism) (MechanismInfo, error) {
   913  	var cm C.CK_MECHANISM_INFO
   914  	e := C.GetMechanismInfo(c.ctx, C.CK_ULONG(slotID), C.CK_MECHANISM_TYPE(m[0].Mechanism),
   915  		C.CK_MECHANISM_INFO_PTR(&cm))
   916  	mi := MechanismInfo{
   917  		MinKeySize: uint(cm.ulMinKeySize),
   918  		MaxKeySize: uint(cm.ulMaxKeySize),
   919  		Flags:      uint(cm.flags),
   920  	}
   921  	return mi, toError(e)
   922  }
   923  
   924  // InitToken initializes a token. The label must be 32 characters
   925  // long, it is blank padded if it is not. If it is longer it is capped
   926  // to 32 characters.
   927  func (c *Ctx) InitToken(slotID uint, pin string, label string) error {
   928  	p := C.CString(pin)
   929  	defer C.free(unsafe.Pointer(p))
   930  	ll := len(label)
   931  	for ll < 32 {
   932  		label += " "
   933  		ll++
   934  	}
   935  	l := C.CString(label[:32])
   936  	defer C.free(unsafe.Pointer(l))
   937  	e := C.InitToken(c.ctx, C.CK_ULONG(slotID), p, C.CK_ULONG(len(pin)), l)
   938  	return toError(e)
   939  }
   940  
   941  // InitPIN initializes the normal user's PIN.
   942  func (c *Ctx) InitPIN(sh SessionHandle, pin string) error {
   943  	p := C.CString(pin)
   944  	defer C.free(unsafe.Pointer(p))
   945  	e := C.InitPIN(c.ctx, C.CK_SESSION_HANDLE(sh), p, C.CK_ULONG(len(pin)))
   946  	return toError(e)
   947  }
   948  
   949  // SetPIN modifies the PIN of the user who is logged in.
   950  func (c *Ctx) SetPIN(sh SessionHandle, oldpin string, newpin string) error {
   951  	old := C.CString(oldpin)
   952  	defer C.free(unsafe.Pointer(old))
   953  	new := C.CString(newpin)
   954  	defer C.free(unsafe.Pointer(new))
   955  	e := C.SetPIN(c.ctx, C.CK_SESSION_HANDLE(sh), old, C.CK_ULONG(len(oldpin)), new, C.CK_ULONG(len(newpin)))
   956  	return toError(e)
   957  }
   958  
   959  // OpenSession opens a session between an application and a token.
   960  func (c *Ctx) OpenSession(slotID uint, flags uint) (SessionHandle, error) {
   961  	var s C.CK_SESSION_HANDLE
   962  	e := C.OpenSession(c.ctx, C.CK_ULONG(slotID), C.CK_ULONG(flags), C.CK_SESSION_HANDLE_PTR(&s))
   963  	return SessionHandle(s), toError(e)
   964  }
   965  
   966  // CloseSession closes a session between an application and a token.
   967  func (c *Ctx) CloseSession(sh SessionHandle) error {
   968  	if c.ctx == nil {
   969  		return toError(CKR_CRYPTOKI_NOT_INITIALIZED)
   970  	}
   971  	e := C.CloseSession(c.ctx, C.CK_SESSION_HANDLE(sh))
   972  	return toError(e)
   973  }
   974  
   975  // CloseAllSessions closes all sessions with a token.
   976  func (c *Ctx) CloseAllSessions(slotID uint) error {
   977  	if c.ctx == nil {
   978  		return toError(CKR_CRYPTOKI_NOT_INITIALIZED)
   979  	}
   980  	e := C.CloseAllSessions(c.ctx, C.CK_ULONG(slotID))
   981  	return toError(e)
   982  }
   983  
   984  // GetSessionInfo obtains information about the session.
   985  func (c *Ctx) GetSessionInfo(sh SessionHandle) (SessionInfo, error) {
   986  	var csi C.CK_SESSION_INFO
   987  	e := C.GetSessionInfo(c.ctx, C.CK_SESSION_HANDLE(sh), &csi)
   988  	s := SessionInfo{SlotID: uint(csi.slotID),
   989  		State:       uint(csi.state),
   990  		Flags:       uint(csi.flags),
   991  		DeviceError: uint(csi.ulDeviceError),
   992  	}
   993  	return s, toError(e)
   994  }
   995  
   996  // GetOperationState obtains the state of the cryptographic operation in a session.
   997  func (c *Ctx) GetOperationState(sh SessionHandle) ([]byte, error) {
   998  	var (
   999  		state    C.CK_BYTE_PTR
  1000  		statelen C.CK_ULONG
  1001  	)
  1002  	e := C.GetOperationState(c.ctx, C.CK_SESSION_HANDLE(sh), &state, &statelen)
  1003  	defer C.free(unsafe.Pointer(state))
  1004  	if toError(e) != nil {
  1005  		return nil, toError(e)
  1006  	}
  1007  	b := C.GoBytes(unsafe.Pointer(state), C.int(statelen))
  1008  	return b, nil
  1009  }
  1010  
  1011  // SetOperationState restores the state of the cryptographic operation in a session.
  1012  func (c *Ctx) SetOperationState(sh SessionHandle, state []byte, encryptKey, authKey ObjectHandle) error {
  1013  	e := C.SetOperationState(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&state[0])),
  1014  		C.CK_ULONG(len(state)), C.CK_OBJECT_HANDLE(encryptKey), C.CK_OBJECT_HANDLE(authKey))
  1015  	return toError(e)
  1016  }
  1017  
  1018  // Login logs a user into a token.
  1019  func (c *Ctx) Login(sh SessionHandle, userType uint, pin string) error {
  1020  	p := C.CString(pin)
  1021  	defer C.free(unsafe.Pointer(p))
  1022  	e := C.Login(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_USER_TYPE(userType), p, C.CK_ULONG(len(pin)))
  1023  	return toError(e)
  1024  }
  1025  
  1026  // Logout logs a user out from a token.
  1027  func (c *Ctx) Logout(sh SessionHandle) error {
  1028  	if c.ctx == nil {
  1029  		return toError(CKR_CRYPTOKI_NOT_INITIALIZED)
  1030  	}
  1031  	e := C.Logout(c.ctx, C.CK_SESSION_HANDLE(sh))
  1032  	return toError(e)
  1033  }
  1034  
  1035  // CreateObject creates a new object.
  1036  func (c *Ctx) CreateObject(sh SessionHandle, temp []*Attribute) (ObjectHandle, error) {
  1037  	var obj C.CK_OBJECT_HANDLE
  1038  	arena, t, tcount := cAttributeList(temp)
  1039  	defer arena.Free()
  1040  	e := C.CreateObject(c.ctx, C.CK_SESSION_HANDLE(sh), t, tcount, C.CK_OBJECT_HANDLE_PTR(&obj))
  1041  	e1 := toError(e)
  1042  	if e1 == nil {
  1043  		return ObjectHandle(obj), nil
  1044  	}
  1045  	return 0, e1
  1046  }
  1047  
  1048  // CopyObject copies an object, creating a new object for the copy.
  1049  func (c *Ctx) CopyObject(sh SessionHandle, o ObjectHandle, temp []*Attribute) (ObjectHandle, error) {
  1050  	var obj C.CK_OBJECT_HANDLE
  1051  	arena, t, tcount := cAttributeList(temp)
  1052  	defer arena.Free()
  1053  
  1054  	e := C.CopyObject(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(o), t, tcount, C.CK_OBJECT_HANDLE_PTR(&obj))
  1055  	e1 := toError(e)
  1056  	if e1 == nil {
  1057  		return ObjectHandle(obj), nil
  1058  	}
  1059  	return 0, e1
  1060  }
  1061  
  1062  // DestroyObject destroys an object.
  1063  func (c *Ctx) DestroyObject(sh SessionHandle, oh ObjectHandle) error {
  1064  	e := C.DestroyObject(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(oh))
  1065  	return toError(e)
  1066  }
  1067  
  1068  // GetObjectSize gets the size of an object in bytes.
  1069  func (c *Ctx) GetObjectSize(sh SessionHandle, oh ObjectHandle) (uint, error) {
  1070  	var size C.CK_ULONG
  1071  	e := C.GetObjectSize(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(oh), &size)
  1072  	return uint(size), toError(e)
  1073  }
  1074  
  1075  // GetAttributeValue obtains the value of one or more object attributes.
  1076  func (c *Ctx) GetAttributeValue(sh SessionHandle, o ObjectHandle, a []*Attribute) ([]*Attribute, error) {
  1077  	// copy the attribute list and make all the values nil, so that
  1078  	// the C function can (allocate) fill them in
  1079  	pa := make([]C.CK_ATTRIBUTE, len(a))
  1080  	for i := 0; i < len(a); i++ {
  1081  		pa[i]._type = C.CK_ATTRIBUTE_TYPE(a[i].Type)
  1082  	}
  1083  	e := C.GetAttributeValue(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(o), &pa[0], C.CK_ULONG(len(a)))
  1084  	if err := toError(e); err != nil {
  1085  		return nil, err
  1086  	}
  1087  	a1 := make([]*Attribute, len(a))
  1088  	for i, c := range pa {
  1089  		x := new(Attribute)
  1090  		x.Type = uint(c._type)
  1091  		if int(c.ulValueLen) != -1 {
  1092  			buf := unsafe.Pointer(C.getAttributePval(&c))
  1093  			x.Value = C.GoBytes(buf, C.int(c.ulValueLen))
  1094  			C.free(buf)
  1095  		}
  1096  		a1[i] = x
  1097  	}
  1098  	return a1, nil
  1099  }
  1100  
  1101  // SetAttributeValue modifies the value of one or more object attributes
  1102  func (c *Ctx) SetAttributeValue(sh SessionHandle, o ObjectHandle, a []*Attribute) error {
  1103  	arena, pa, palen := cAttributeList(a)
  1104  	defer arena.Free()
  1105  	e := C.SetAttributeValue(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(o), pa, palen)
  1106  	return toError(e)
  1107  }
  1108  
  1109  // FindObjectsInit initializes a search for token and session
  1110  // objects that match a template.
  1111  func (c *Ctx) FindObjectsInit(sh SessionHandle, temp []*Attribute) error {
  1112  	arena, t, tcount := cAttributeList(temp)
  1113  	defer arena.Free()
  1114  	e := C.FindObjectsInit(c.ctx, C.CK_SESSION_HANDLE(sh), t, tcount)
  1115  	return toError(e)
  1116  }
  1117  
  1118  // FindObjects continues a search for token and session
  1119  // objects that match a template, obtaining additional object
  1120  // handles. Calling the function repeatedly may yield additional results until
  1121  // an empty slice is returned.
  1122  //
  1123  // The returned boolean value is deprecated and should be ignored.
  1124  func (c *Ctx) FindObjects(sh SessionHandle, max int) ([]ObjectHandle, bool, error) {
  1125  	var (
  1126  		objectList C.CK_OBJECT_HANDLE_PTR
  1127  		ulCount    C.CK_ULONG
  1128  	)
  1129  	e := C.FindObjects(c.ctx, C.CK_SESSION_HANDLE(sh), &objectList, C.CK_ULONG(max), &ulCount)
  1130  	if toError(e) != nil {
  1131  		return nil, false, toError(e)
  1132  	}
  1133  	l := toList(C.CK_ULONG_PTR(unsafe.Pointer(objectList)), ulCount)
  1134  	// Make again a new list of the correct type.
  1135  	// This is copying data, but this is not an often used function.
  1136  	o := make([]ObjectHandle, len(l))
  1137  	for i, v := range l {
  1138  		o[i] = ObjectHandle(v)
  1139  	}
  1140  	return o, ulCount > C.CK_ULONG(max), nil
  1141  }
  1142  
  1143  // FindObjectsFinal finishes a search for token and session objects.
  1144  func (c *Ctx) FindObjectsFinal(sh SessionHandle) error {
  1145  	e := C.FindObjectsFinal(c.ctx, C.CK_SESSION_HANDLE(sh))
  1146  	return toError(e)
  1147  }
  1148  
  1149  // EncryptInit initializes an encryption operation.
  1150  func (c *Ctx) EncryptInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
  1151  	arena, mech := cMechanism(m)
  1152  	defer arena.Free()
  1153  	e := C.EncryptInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
  1154  	return toError(e)
  1155  }
  1156  
  1157  // Encrypt encrypts single-part data.
  1158  func (c *Ctx) Encrypt(sh SessionHandle, message []byte) ([]byte, error) {
  1159  	var (
  1160  		enc    C.CK_BYTE_PTR
  1161  		enclen C.CK_ULONG
  1162  	)
  1163  	e := C.Encrypt(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)), &enc, &enclen)
  1164  	if toError(e) != nil {
  1165  		return nil, toError(e)
  1166  	}
  1167  	s := C.GoBytes(unsafe.Pointer(enc), C.int(enclen))
  1168  	C.free(unsafe.Pointer(enc))
  1169  	return s, nil
  1170  }
  1171  
  1172  // EncryptUpdate continues a multiple-part encryption operation.
  1173  func (c *Ctx) EncryptUpdate(sh SessionHandle, plain []byte) ([]byte, error) {
  1174  	var (
  1175  		part    C.CK_BYTE_PTR
  1176  		partlen C.CK_ULONG
  1177  	)
  1178  	e := C.EncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(plain), C.CK_ULONG(len(plain)), &part, &partlen)
  1179  	if toError(e) != nil {
  1180  		return nil, toError(e)
  1181  	}
  1182  	h := C.GoBytes(unsafe.Pointer(part), C.int(partlen))
  1183  	C.free(unsafe.Pointer(part))
  1184  	return h, nil
  1185  }
  1186  
  1187  // EncryptFinal finishes a multiple-part encryption operation.
  1188  func (c *Ctx) EncryptFinal(sh SessionHandle) ([]byte, error) {
  1189  	var (
  1190  		enc    C.CK_BYTE_PTR
  1191  		enclen C.CK_ULONG
  1192  	)
  1193  	e := C.EncryptFinal(c.ctx, C.CK_SESSION_HANDLE(sh), &enc, &enclen)
  1194  	if toError(e) != nil {
  1195  		return nil, toError(e)
  1196  	}
  1197  	h := C.GoBytes(unsafe.Pointer(enc), C.int(enclen))
  1198  	C.free(unsafe.Pointer(enc))
  1199  	return h, nil
  1200  }
  1201  
  1202  // DecryptInit initializes a decryption operation.
  1203  func (c *Ctx) DecryptInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
  1204  	arena, mech := cMechanism(m)
  1205  	defer arena.Free()
  1206  	e := C.DecryptInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
  1207  	return toError(e)
  1208  }
  1209  
  1210  // Decrypt decrypts encrypted data in a single part.
  1211  func (c *Ctx) Decrypt(sh SessionHandle, cipher []byte) ([]byte, error) {
  1212  	var (
  1213  		plain    C.CK_BYTE_PTR
  1214  		plainlen C.CK_ULONG
  1215  	)
  1216  	e := C.Decrypt(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(cipher), C.CK_ULONG(len(cipher)), &plain, &plainlen)
  1217  	if toError(e) != nil {
  1218  		return nil, toError(e)
  1219  	}
  1220  	s := C.GoBytes(unsafe.Pointer(plain), C.int(plainlen))
  1221  	C.free(unsafe.Pointer(plain))
  1222  	return s, nil
  1223  }
  1224  
  1225  // DecryptUpdate continues a multiple-part decryption operation.
  1226  func (c *Ctx) DecryptUpdate(sh SessionHandle, cipher []byte) ([]byte, error) {
  1227  	var (
  1228  		part    C.CK_BYTE_PTR
  1229  		partlen C.CK_ULONG
  1230  	)
  1231  	e := C.DecryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(cipher), C.CK_ULONG(len(cipher)), &part, &partlen)
  1232  	if toError(e) != nil {
  1233  		return nil, toError(e)
  1234  	}
  1235  	h := C.GoBytes(unsafe.Pointer(part), C.int(partlen))
  1236  	C.free(unsafe.Pointer(part))
  1237  	return h, nil
  1238  }
  1239  
  1240  // DecryptFinal finishes a multiple-part decryption operation.
  1241  func (c *Ctx) DecryptFinal(sh SessionHandle) ([]byte, error) {
  1242  	var (
  1243  		plain    C.CK_BYTE_PTR
  1244  		plainlen C.CK_ULONG
  1245  	)
  1246  	e := C.DecryptFinal(c.ctx, C.CK_SESSION_HANDLE(sh), &plain, &plainlen)
  1247  	if toError(e) != nil {
  1248  		return nil, toError(e)
  1249  	}
  1250  	h := C.GoBytes(unsafe.Pointer(plain), C.int(plainlen))
  1251  	C.free(unsafe.Pointer(plain))
  1252  	return h, nil
  1253  }
  1254  
  1255  // DigestInit initializes a message-digesting operation.
  1256  func (c *Ctx) DigestInit(sh SessionHandle, m []*Mechanism) error {
  1257  	arena, mech := cMechanism(m)
  1258  	defer arena.Free()
  1259  	e := C.DigestInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech)
  1260  	return toError(e)
  1261  }
  1262  
  1263  // Digest digests message in a single part.
  1264  func (c *Ctx) Digest(sh SessionHandle, message []byte) ([]byte, error) {
  1265  	var (
  1266  		hash    C.CK_BYTE_PTR
  1267  		hashlen C.CK_ULONG
  1268  	)
  1269  	e := C.Digest(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)), &hash, &hashlen)
  1270  	if toError(e) != nil {
  1271  		return nil, toError(e)
  1272  	}
  1273  	h := C.GoBytes(unsafe.Pointer(hash), C.int(hashlen))
  1274  	C.free(unsafe.Pointer(hash))
  1275  	return h, nil
  1276  }
  1277  
  1278  // DigestUpdate continues a multiple-part message-digesting operation.
  1279  func (c *Ctx) DigestUpdate(sh SessionHandle, message []byte) error {
  1280  	e := C.DigestUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)))
  1281  	if toError(e) != nil {
  1282  		return toError(e)
  1283  	}
  1284  	return nil
  1285  }
  1286  
  1287  // DigestKey continues a multi-part message-digesting
  1288  // operation, by digesting the value of a secret key as part of
  1289  // the data already digested.
  1290  func (c *Ctx) DigestKey(sh SessionHandle, key ObjectHandle) error {
  1291  	e := C.DigestKey(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(key))
  1292  	if toError(e) != nil {
  1293  		return toError(e)
  1294  	}
  1295  	return nil
  1296  }
  1297  
  1298  // DigestFinal finishes a multiple-part message-digesting operation.
  1299  func (c *Ctx) DigestFinal(sh SessionHandle) ([]byte, error) {
  1300  	var (
  1301  		hash    C.CK_BYTE_PTR
  1302  		hashlen C.CK_ULONG
  1303  	)
  1304  	e := C.DigestFinal(c.ctx, C.CK_SESSION_HANDLE(sh), &hash, &hashlen)
  1305  	if toError(e) != nil {
  1306  		return nil, toError(e)
  1307  	}
  1308  	h := C.GoBytes(unsafe.Pointer(hash), C.int(hashlen))
  1309  	C.free(unsafe.Pointer(hash))
  1310  	return h, nil
  1311  }
  1312  
  1313  // SignInit initializes a signature (private key encryption)
  1314  // operation, where the signature is (will be) an appendix to
  1315  // the data, and plaintext cannot be recovered from the signature.
  1316  func (c *Ctx) SignInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
  1317  	arena, mech := cMechanism(m)
  1318  	defer arena.Free()
  1319  	e := C.SignInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
  1320  	return toError(e)
  1321  }
  1322  
  1323  // Sign signs (encrypts with private key) data in a single part, where the signature
  1324  // is (will be) an appendix to the data, and plaintext cannot be recovered from the signature.
  1325  func (c *Ctx) Sign(sh SessionHandle, message []byte) ([]byte, error) {
  1326  	var (
  1327  		sig    C.CK_BYTE_PTR
  1328  		siglen C.CK_ULONG
  1329  	)
  1330  	e := C.Sign(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)), &sig, &siglen)
  1331  	if toError(e) != nil {
  1332  		return nil, toError(e)
  1333  	}
  1334  	s := C.GoBytes(unsafe.Pointer(sig), C.int(siglen))
  1335  	C.free(unsafe.Pointer(sig))
  1336  	return s, nil
  1337  }
  1338  
  1339  // SignUpdate continues a multiple-part signature operation,
  1340  // where the signature is (will be) an appendix to the data,
  1341  // and plaintext cannot be recovered from the signature.
  1342  func (c *Ctx) SignUpdate(sh SessionHandle, message []byte) error {
  1343  	e := C.SignUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)))
  1344  	return toError(e)
  1345  }
  1346  
  1347  // SignFinal finishes a multiple-part signature operation returning the signature.
  1348  func (c *Ctx) SignFinal(sh SessionHandle) ([]byte, error) {
  1349  	var (
  1350  		sig    C.CK_BYTE_PTR
  1351  		siglen C.CK_ULONG
  1352  	)
  1353  	e := C.SignFinal(c.ctx, C.CK_SESSION_HANDLE(sh), &sig, &siglen)
  1354  	if toError(e) != nil {
  1355  		return nil, toError(e)
  1356  	}
  1357  	h := C.GoBytes(unsafe.Pointer(sig), C.int(siglen))
  1358  	C.free(unsafe.Pointer(sig))
  1359  	return h, nil
  1360  }
  1361  
  1362  // SignRecoverInit initializes a signature operation, where the data can be recovered from the signature.
  1363  func (c *Ctx) SignRecoverInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
  1364  	arena, mech := cMechanism(m)
  1365  	defer arena.Free()
  1366  	e := C.SignRecoverInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
  1367  	return toError(e)
  1368  }
  1369  
  1370  // SignRecover signs data in a single operation, where the data can be recovered from the signature.
  1371  func (c *Ctx) SignRecover(sh SessionHandle, data []byte) ([]byte, error) {
  1372  	var (
  1373  		sig    C.CK_BYTE_PTR
  1374  		siglen C.CK_ULONG
  1375  	)
  1376  	e := C.SignRecover(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(data), C.CK_ULONG(len(data)), &sig, &siglen)
  1377  	if toError(e) != nil {
  1378  		return nil, toError(e)
  1379  	}
  1380  	h := C.GoBytes(unsafe.Pointer(sig), C.int(siglen))
  1381  	C.free(unsafe.Pointer(sig))
  1382  	return h, nil
  1383  }
  1384  
  1385  // VerifyInit initializes a verification operation, where the
  1386  // signature is an appendix to the data, and plaintext cannot
  1387  // be recovered from the signature (e.g. DSA).
  1388  func (c *Ctx) VerifyInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
  1389  	arena, mech := cMechanism(m)
  1390  	defer arena.Free()
  1391  	e := C.VerifyInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
  1392  	return toError(e)
  1393  }
  1394  
  1395  // Verify verifies a signature in a single-part operation,
  1396  // where the signature is an appendix to the data, and plaintext
  1397  // cannot be recovered from the signature.
  1398  func (c *Ctx) Verify(sh SessionHandle, data []byte, signature []byte) error {
  1399  	e := C.Verify(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(data), C.CK_ULONG(len(data)), cMessage(signature), C.CK_ULONG(len(signature)))
  1400  	return toError(e)
  1401  }
  1402  
  1403  // VerifyUpdate continues a multiple-part verification
  1404  // operation, where the signature is an appendix to the data,
  1405  // and plaintext cannot be recovered from the signature.
  1406  func (c *Ctx) VerifyUpdate(sh SessionHandle, part []byte) error {
  1407  	e := C.VerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(part), C.CK_ULONG(len(part)))
  1408  	return toError(e)
  1409  }
  1410  
  1411  // VerifyFinal finishes a multiple-part verification
  1412  // operation, checking the signature.
  1413  func (c *Ctx) VerifyFinal(sh SessionHandle, signature []byte) error {
  1414  	e := C.VerifyFinal(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(signature), C.CK_ULONG(len(signature)))
  1415  	return toError(e)
  1416  }
  1417  
  1418  // VerifyRecoverInit initializes a signature verification
  1419  // operation, where the data is recovered from the signature.
  1420  func (c *Ctx) VerifyRecoverInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
  1421  	arena, mech := cMechanism(m)
  1422  	defer arena.Free()
  1423  	e := C.VerifyRecoverInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
  1424  	return toError(e)
  1425  }
  1426  
  1427  // VerifyRecover verifies a signature in a single-part
  1428  // operation, where the data is recovered from the signature.
  1429  func (c *Ctx) VerifyRecover(sh SessionHandle, signature []byte) ([]byte, error) {
  1430  	var (
  1431  		data    C.CK_BYTE_PTR
  1432  		datalen C.CK_ULONG
  1433  	)
  1434  	e := C.DecryptVerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(signature), C.CK_ULONG(len(signature)), &data, &datalen)
  1435  	if toError(e) != nil {
  1436  		return nil, toError(e)
  1437  	}
  1438  	h := C.GoBytes(unsafe.Pointer(data), C.int(datalen))
  1439  	C.free(unsafe.Pointer(data))
  1440  	return h, nil
  1441  }
  1442  
  1443  // DigestEncryptUpdate continues a multiple-part digesting and encryption operation.
  1444  func (c *Ctx) DigestEncryptUpdate(sh SessionHandle, part []byte) ([]byte, error) {
  1445  	var (
  1446  		enc    C.CK_BYTE_PTR
  1447  		enclen C.CK_ULONG
  1448  	)
  1449  	e := C.DigestEncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(part), C.CK_ULONG(len(part)), &enc, &enclen)
  1450  	if toError(e) != nil {
  1451  		return nil, toError(e)
  1452  	}
  1453  	h := C.GoBytes(unsafe.Pointer(enc), C.int(enclen))
  1454  	C.free(unsafe.Pointer(enc))
  1455  	return h, nil
  1456  }
  1457  
  1458  // DecryptDigestUpdate continues a multiple-part decryption and digesting operation.
  1459  func (c *Ctx) DecryptDigestUpdate(sh SessionHandle, cipher []byte) ([]byte, error) {
  1460  	var (
  1461  		part    C.CK_BYTE_PTR
  1462  		partlen C.CK_ULONG
  1463  	)
  1464  	e := C.DecryptDigestUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(cipher), C.CK_ULONG(len(cipher)), &part, &partlen)
  1465  	if toError(e) != nil {
  1466  		return nil, toError(e)
  1467  	}
  1468  	h := C.GoBytes(unsafe.Pointer(part), C.int(partlen))
  1469  	C.free(unsafe.Pointer(part))
  1470  	return h, nil
  1471  }
  1472  
  1473  // SignEncryptUpdate continues a multiple-part signing and encryption operation.
  1474  func (c *Ctx) SignEncryptUpdate(sh SessionHandle, part []byte) ([]byte, error) {
  1475  	var (
  1476  		enc    C.CK_BYTE_PTR
  1477  		enclen C.CK_ULONG
  1478  	)
  1479  	e := C.SignEncryptUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(part), C.CK_ULONG(len(part)), &enc, &enclen)
  1480  	if toError(e) != nil {
  1481  		return nil, toError(e)
  1482  	}
  1483  	h := C.GoBytes(unsafe.Pointer(enc), C.int(enclen))
  1484  	C.free(unsafe.Pointer(enc))
  1485  	return h, nil
  1486  }
  1487  
  1488  // DecryptVerifyUpdate continues a multiple-part decryption and verify operation.
  1489  func (c *Ctx) DecryptVerifyUpdate(sh SessionHandle, cipher []byte) ([]byte, error) {
  1490  	var (
  1491  		part    C.CK_BYTE_PTR
  1492  		partlen C.CK_ULONG
  1493  	)
  1494  	e := C.DecryptVerifyUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(cipher), C.CK_ULONG(len(cipher)), &part, &partlen)
  1495  	if toError(e) != nil {
  1496  		return nil, toError(e)
  1497  	}
  1498  	h := C.GoBytes(unsafe.Pointer(part), C.int(partlen))
  1499  	C.free(unsafe.Pointer(part))
  1500  	return h, nil
  1501  }
  1502  
  1503  // GenerateKey generates a secret key, creating a new key object.
  1504  func (c *Ctx) GenerateKey(sh SessionHandle, m []*Mechanism, temp []*Attribute) (ObjectHandle, error) {
  1505  	var key C.CK_OBJECT_HANDLE
  1506  	attrarena, t, tcount := cAttributeList(temp)
  1507  	defer attrarena.Free()
  1508  	mecharena, mech := cMechanism(m)
  1509  	defer mecharena.Free()
  1510  	e := C.GenerateKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, t, tcount, C.CK_OBJECT_HANDLE_PTR(&key))
  1511  	e1 := toError(e)
  1512  	if e1 == nil {
  1513  		return ObjectHandle(key), nil
  1514  	}
  1515  	return 0, e1
  1516  }
  1517  
  1518  // GenerateKeyPair generates a public-key/private-key pair creating new key objects.
  1519  func (c *Ctx) GenerateKeyPair(sh SessionHandle, m []*Mechanism, public, private []*Attribute) (ObjectHandle, ObjectHandle, error) {
  1520  	var (
  1521  		pubkey  C.CK_OBJECT_HANDLE
  1522  		privkey C.CK_OBJECT_HANDLE
  1523  	)
  1524  	pubarena, pub, pubcount := cAttributeList(public)
  1525  	defer pubarena.Free()
  1526  	privarena, priv, privcount := cAttributeList(private)
  1527  	defer privarena.Free()
  1528  	mecharena, mech := cMechanism(m)
  1529  	defer mecharena.Free()
  1530  	e := C.GenerateKeyPair(c.ctx, C.CK_SESSION_HANDLE(sh), mech, pub, pubcount, priv, privcount, C.CK_OBJECT_HANDLE_PTR(&pubkey), C.CK_OBJECT_HANDLE_PTR(&privkey))
  1531  	e1 := toError(e)
  1532  	if e1 == nil {
  1533  		return ObjectHandle(pubkey), ObjectHandle(privkey), nil
  1534  	}
  1535  	return 0, 0, e1
  1536  }
  1537  
  1538  // WrapKey wraps (i.e., encrypts) a key.
  1539  func (c *Ctx) WrapKey(sh SessionHandle, m []*Mechanism, wrappingkey, key ObjectHandle) ([]byte, error) {
  1540  	var (
  1541  		wrappedkey    C.CK_BYTE_PTR
  1542  		wrappedkeylen C.CK_ULONG
  1543  	)
  1544  	arena, mech := cMechanism(m)
  1545  	defer arena.Free()
  1546  	e := C.WrapKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(wrappingkey), C.CK_OBJECT_HANDLE(key), &wrappedkey, &wrappedkeylen)
  1547  	if toError(e) != nil {
  1548  		return nil, toError(e)
  1549  	}
  1550  	h := C.GoBytes(unsafe.Pointer(wrappedkey), C.int(wrappedkeylen))
  1551  	C.free(unsafe.Pointer(wrappedkey))
  1552  	return h, nil
  1553  }
  1554  
  1555  // UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object.
  1556  func (c *Ctx) UnwrapKey(sh SessionHandle, m []*Mechanism, unwrappingkey ObjectHandle, wrappedkey []byte, a []*Attribute) (ObjectHandle, error) {
  1557  	var key C.CK_OBJECT_HANDLE
  1558  	attrarena, ac, aclen := cAttributeList(a)
  1559  	defer attrarena.Free()
  1560  	mecharena, mech := cMechanism(m)
  1561  	defer mecharena.Free()
  1562  	e := C.UnwrapKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(unwrappingkey), C.CK_BYTE_PTR(unsafe.Pointer(&wrappedkey[0])), C.CK_ULONG(len(wrappedkey)), ac, aclen, &key)
  1563  	return ObjectHandle(key), toError(e)
  1564  }
  1565  
  1566  // DeriveKey derives a key from a base key, creating a new key object.
  1567  func (c *Ctx) DeriveKey(sh SessionHandle, m []*Mechanism, basekey ObjectHandle, a []*Attribute) (ObjectHandle, error) {
  1568  	var key C.CK_OBJECT_HANDLE
  1569  	attrarena, ac, aclen := cAttributeList(a)
  1570  	defer attrarena.Free()
  1571  	mecharena, mech := cMechanism(m)
  1572  	defer mecharena.Free()
  1573  	e := C.DeriveKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(basekey), ac, aclen, &key)
  1574  	return ObjectHandle(key), toError(e)
  1575  }
  1576  
  1577  // SeedRandom mixes additional seed material into the token's
  1578  // random number generator.
  1579  func (c *Ctx) SeedRandom(sh SessionHandle, seed []byte) error {
  1580  	e := C.SeedRandom(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_BYTE_PTR(unsafe.Pointer(&seed[0])), C.CK_ULONG(len(seed)))
  1581  	return toError(e)
  1582  }
  1583  
  1584  // GenerateRandom generates random data.
  1585  func (c *Ctx) GenerateRandom(sh SessionHandle, length int) ([]byte, error) {
  1586  	var rand C.CK_BYTE_PTR
  1587  	e := C.GenerateRandom(c.ctx, C.CK_SESSION_HANDLE(sh), &rand, C.CK_ULONG(length))
  1588  	if toError(e) != nil {
  1589  		return nil, toError(e)
  1590  	}
  1591  	h := C.GoBytes(unsafe.Pointer(rand), C.int(length))
  1592  	C.free(unsafe.Pointer(rand))
  1593  	return h, nil
  1594  }
  1595  
  1596  // WaitForSlotEvent returns a channel which returns a slot event
  1597  // (token insertion, removal, etc.) when it occurs.
  1598  func (c *Ctx) WaitForSlotEvent(flags uint) chan SlotEvent {
  1599  	sl := make(chan SlotEvent, 1) // hold one element
  1600  	go c.waitForSlotEventHelper(flags, sl)
  1601  	return sl
  1602  }
  1603  
  1604  func (c *Ctx) waitForSlotEventHelper(f uint, sl chan SlotEvent) {
  1605  	var slotID C.CK_ULONG
  1606  	C.WaitForSlotEvent(c.ctx, C.CK_FLAGS(f), &slotID)
  1607  	sl <- SlotEvent{uint(slotID)}
  1608  	close(sl) // TODO(miek): Sending and then closing ...?
  1609  }
  1610  

View as plain text