A successful call to C_VerifyFinal should return either the value CKR_OK (indicating that the supplied signature is valid) or CKR_SIGNATURE_INVALID (indicating that the supplied signature is invalid). If the signature can be seen to be invalid purely on the basis of its length, then CKR_SIGNATURE_LEN_RANGE should be returned. In any of these cases, the active verifying operation is terminated.
Return values: CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE.
Example:
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hKey;
CK_MECHANISM mechanism = {
CKM_DES_MAC, NULL_PTR, 0
};
CK_BYTE data[] = {...};
CK_BYTE mac[4];
CK_RV rv;
.
.
rv = C_VerifyInit(hSession, &mechanism, hKey);
if (rv == CKR_OK) {
rv = C_VerifyUpdate(hSession, data, sizeof(data));
.
.
rv = C_VerifyFinal(hSession, mac, sizeof(mac));
.
.
}
CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecoverInit)(
CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey
);
C_VerifyRecoverInit initializes a signature verification operation, where the data is recovered from the signature. hSession is the session’s handle; pMechanism points to the structure that specifies the verification mechanism; hKey is the handle of the verification key.
The CKA_VERIFY_RECOVER attribute of the verification key, which indicates whether the key supports verification where the data is recovered from the signature, MUST be CK_TRUE.
After calling C_VerifyRecoverInit, the application may call C_VerifyRecover to verify a signature on data in a single part. The verification operation is active until the application uses a call to C_VerifyRecover to actually obtain the recovered message.
Return values: CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_KEY_HANDLE_INVALID, CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN.
Example: see C_VerifyRecover.
CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecover)(
CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pSignature,
CK_ULONG ulSignatureLen,
CK_BYTE_PTR pData,
CK_ULONG_PTR pulDataLen
);
C_VerifyRecover verifies a signature in a single-part operation, where the data is recovered from the signature. hSession is the session’s handle; pSignature points to the signature; ulSignatureLen is the length of the signature; pData points to the location that receives the recovered data; and pulDataLen points to the location that holds the length of the recovered data.
C_VerifyRecover uses the convention described in Section 5.2 on producing output.
The verification operation MUST have been initialized with C_VerifyRecoverInit. A call to C_VerifyRecover always terminates the active verification operation unless it returns CKR_BUFFER_TOO_SMALL or is a successful call (i.e., one which returns CKR_OK) to determine the length of the buffer needed to hold the recovered data.
A successful call to C_VerifyRecover should return either the value CKR_OK (indicating that the supplied signature is valid) or CKR_SIGNATURE_INVALID (indicating that the supplied signature is invalid). If the signature can be seen to be invalid purely on the basis of its length, then CKR_SIGNATURE_LEN_RANGE should be returned. The return codes CKR_SIGNATURE_INVALID and CKR_SIGNATURE_LEN_RANGE have a higher priority than the return code CKR_BUFFER_TOO_SMALL, i.e., if C_VerifyRecover is supplied with an invalid signature, it will never return CKR_BUFFER_TOO_SMALL.
Return values: CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_INVALID, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SIGNATURE_LEN_RANGE, CKR_SIGNATURE_INVALID.
Example:
CK_OBJECT_HANDLE hKey;
CK_MECHANISM mechanism = {
CKM_RSA_9796, NULL_PTR, 0
};
CK_BYTE data[] = {...};
CK_ULONG ulDataLen;
CK_BYTE signature[128];
CK_RV rv;
.
.
rv = C_VerifyRecoverInit(hSession, &mechanism, hKey);
if (rv == CKR_OK) {
ulDataLen = sizeof(data);
rv = C_VerifyRecover(
hSession, signature, sizeof(signature), data, &ulDataLen);
.
.
}
Cryptoki provides the following functions to perform two cryptographic operations “simultaneously” within a session. These functions are provided so as to avoid unnecessarily passing data back and forth to and from a token.
CK_DEFINE_FUNCTION(CK_RV, C_DigestEncryptUpdate)(
CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen,
CK_BYTE_PTR pEncryptedPart,
CK_ULONG_PTR pulEncryptedPartLen
);
C_DigestEncryptUpdate continues multiple-part digest and encryption operations, processing another data part. hSession is the session’s handle; pPart points to the data part; ulPartLen is the length of the data part; pEncryptedPart points to the location that receives the digested and encrypted data part; pulEncryptedPartLen points to the location that holds the length of the encrypted data part.
C_DigestEncryptUpdate uses the convention described in Section 5.2 on producing output. If a C_DigestEncryptUpdate call does not produce encrypted output (because an error occurs, or because pEncryptedPart has the value NULL_PTR, or because pulEncryptedPartLen is too small to hold the entire encrypted part output), then no plaintext is passed to the active digest operation.
Digest and encryption operations MUST both be active (they MUST have been initialized with C_DigestInit and C_EncryptInit, respectively). This function may be called any number of times in succession, and may be interspersed with C_DigestUpdate, C_DigestKey, and C_EncryptUpdate calls (it would be somewhat unusual to intersperse calls to C_DigestEncryptUpdate with calls to C_DigestKey, however).
Return values: CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID.
Example:
#define BUF_SZ 512
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hKey;
CK_BYTE iv[8];
CK_MECHANISM digestMechanism = {
CKM_MD5, NULL_PTR, 0
};
CK_MECHANISM encryptionMechanism = {
CKM_DES_ECB, iv, sizeof(iv)
};
CK_BYTE encryptedData[BUF_SZ];
CK_ULONG ulEncryptedDataLen;
CK_BYTE digest[16];
CK_ULONG ulDigestLen;
CK_BYTE data[(2*BUF_SZ)+8];
CK_RV rv;
int i;
.
.
memset(iv, 0, sizeof(iv));
memset(data, ‘A’, ((2*BUF_SZ)+5));
rv = C_EncryptInit(hSession, &encryptionMechanism, hKey);
if (rv != CKR_OK) {
.
.
}
rv = C_DigestInit(hSession, &digestMechanism);
if (rv != CKR_OK) {
.
.
}
ulEncryptedDataLen = sizeof(encryptedData);
rv = C_DigestEncryptUpdate(
hSession,
&data[0], BUF_SZ,
encryptedData, &ulEncryptedDataLen);
.
.
ulEncryptedDataLen = sizeof(encryptedData);
rv = C_DigestEncryptUpdate(
hSession,
&data[BUF_SZ], BUF_SZ,
encryptedData, &ulEncryptedDataLen);
.
.
/*
* The last portion of the buffer needs to be
* handled with separate calls to deal with
* padding issues in ECB mode
*/
/* First, complete the digest on the buffer */
rv = C_DigestUpdate(hSession, &data[BUF_SZ*2], 5);
.
.
ulDigestLen = sizeof(digest);
rv = C_DigestFinal(hSession, digest, &ulDigestLen);
.
.

CK_DEFINE_FUNCTION(CK_RV, C_DecryptDigestUpdate)(
CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedPart,
CK_ULONG ulEncryptedPartLen,
CK_BYTE_PTR pPart,
CK_ULONG_PTR pulPartLen
);
C_DecryptDigestUpdate continues a multiple-part combined decryption and digest operation, processing another data part. hSession is the session’s handle; pEncryptedPart points to the encrypted data part; ulEncryptedPartLen is the length of the encrypted data part; pPart points to the location that receives the recovered data part; pulPartLen points to the location that holds the length of the recovered data part.
C_DecryptDigestUpdate uses the convention described in Section 5.2 on producing output. If a C_DecryptDigestUpdate call does not produce decrypted output (because an error occurs, or because pPart has the value NULL_PTR, or because pulPartLen is too small to hold the entire decrypted part output), then no plaintext is passed to the active digest operation.
Decryption and digesting operations MUST both be active (they MUST have been initialized with C_DecryptInit and C_DigestInit, respectively). This function may be called any number of times in succession, and may be interspersed with C_DecryptUpdate, C_DigestUpdate, and C_DigestKey calls (it would be somewhat unusual to intersperse calls to C_DigestEncryptUpdate with calls to C_DigestKey, however).
Use of C_DecryptDigestUpdate involves a pipelining issue that does not arise when using C_DigestEncryptUpdate, the “inverse function” of C_DecryptDigestUpdate. This is because when C_DigestEncryptUpdate is called, precisely the same input is passed to both the active digesting operation and the active encryption operation; however, when C_DecryptDigestUpdate is called, the input passed to the active digesting operation is the output of the active decryption operation. This issue comes up only when the mechanism used for decryption performs padding.
In particular, envision a 24-byte ciphertext which was obtained by encrypting an 18-byte plaintext with DES in CBC mode with PKCS padding. Consider an application which will simultaneously decrypt this ciphertext and digest the original plaintext thereby obtained.
After initializing decryption and digesting operations, the application passes the 24-byte ciphertext (3 DES blocks) into C_DecryptDigestUpdate. C_DecryptDigestUpdate returns exactly 16 bytes of plaintext, since at this point, Cryptoki doesn’t know if there’s more ciphertext coming, or if the last block of ciphertext held any padding. These 16 bytes of plaintext are passed into the active digesting operation.
Since there is no more ciphertext, the application calls C_DecryptFinal. This tells Cryptoki that there’s no more ciphertext coming, and the call returns the last 2 bytes of plaintext. However, since the active decryption and digesting operations are linked only through the C_DecryptDigestUpdate call, these 2 bytes of plaintext are not passed on to be digested.
A call to C_DigestFinal, therefore, would compute the message digest of the first 16 bytes of the plaintext, not the message digest of the entire plaintext. It is crucial that, before C_DigestFinal is called, the last 2 bytes of plaintext get passed into the active digesting operation via a C_DigestUpdate call.
Because of this, it is critical that when an application uses a padded decryption mechanism with C_DecryptDigestUpdate, it knows exactly how much plaintext has been passed into the active digesting operation. Extreme caution is warranted when using a padded decryption mechanism with C_DecryptDigestUpdate.
Return values: CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID.
Example:
#define BUF_SZ 512
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hKey;
CK_BYTE iv[8];
CK_MECHANISM decryptionMechanism = {
CKM_DES_ECB, iv, sizeof(iv)
};
CK_MECHANISM digestMechanism = {
CKM_MD5, NULL_PTR, 0
};
CK_BYTE encryptedData[(2*BUF_SZ)+8];
CK_BYTE digest[16];
CK_ULONG ulDigestLen;
CK_BYTE data[BUF_SZ];
CK_ULONG ulDataLen, ulLastUpdateSize;
CK_RV rv;
.
.
memset(iv, 0, sizeof(iv));
memset(encryptedData, ‘A’, ((2*BUF_SZ)+8));
rv = C_DecryptInit(hSession, &decryptionMechanism, hKey);
if (rv != CKR_OK) {
.
.
}
rv = C_DigestInit(hSession, &digestMechanism);
if (rv != CKR_OK){
.
.
}
ulDataLen = sizeof(data);
rv = C_DecryptDigestUpdate(
hSession,
&encryptedData[0], BUF_SZ,
data, &ulDataLen);
.
.
ulDataLen = sizeof(data);
rv = C_DecryptDigestUpdate(
hSession,
&encryptedData[BUF_SZ], BUF_SZ,
data, &ulDataLen);
.
.
/*
* The last portion of the buffer needs to be handled with
* separate calls to deal with padding issues in ECB mode
*/
/* First, complete the decryption of the buffer */
ulLastUpdateSize = sizeof(data);
rv = C_DecryptUpdate(
hSession,
&encryptedData[BUF_SZ*2], 8,
data, &ulLastUpdateSize);
.
.
/* Get last piece of plaintext (should have length 0, here) */
ulDataLen = sizeof(data)-ulLastUpdateSize;
rv = C_DecryptFinal(hSession, &data[ulLastUpdateSize], &ulDataLen);
if (rv != CKR_OK) {
.
.
}
/* Digest last bit of plaintext */
rv = C_DigestUpdate(hSession, &data[BUF_SZ*2], 5);
if (rv != CKR_OK) {
.
.
}
ulDigestLen = sizeof(digest);
rv = C_DigestFinal(hSession, digest, &ulDigestLen);
if (rv != CKR_OK) {
.
.
}
CK_DEFINE_FUNCTION(CK_RV, C_SignEncryptUpdate)(
CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pPart,
CK_ULONG ulPartLen,
CK_BYTE_PTR pEncryptedPart,
CK_ULONG_PTR pulEncryptedPartLen
);
C_SignEncryptUpdate continues a multiple-part combined signature and encryption operation, processing another data part. hSession is the session’s handle; pPart points to the data part; ulPartLen is the length of the data part; pEncryptedPart points to the location that receives the digested and encrypted data part; and pulEncryptedPartLen points to the location that holds the length of the encrypted data part.
C_SignEncryptUpdate uses the convention described in Section 5.2 on producing output. If a C_SignEncryptUpdate call does not produce encrypted output (because an error occurs, or because pEncryptedPart has the value NULL_PTR, or because pulEncryptedPartLen is too small to hold the entire encrypted part output), then no plaintext is passed to the active signing operation.
Signature and encryption operations MUST both be active (they MUST have been initialized with C_SignInit and C_EncryptInit, respectively). This function may be called any number of times in succession, and may be interspersed with C_SignUpdate and C_EncryptUpdate calls.
Return values: CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN.
Example:
#define BUF_SZ 512
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hEncryptionKey, hMacKey;
CK_BYTE iv[8];
CK_MECHANISM signMechanism = {
CKM_DES_MAC, NULL_PTR, 0
};
CK_MECHANISM encryptionMechanism = {
CKM_DES_ECB, iv, sizeof(iv)
};
CK_BYTE encryptedData[BUF_SZ];
CK_ULONG ulEncryptedDataLen;
CK_BYTE MAC[4];
CK_ULONG ulMacLen;
CK_BYTE data[(2*BUF_SZ)+8];
CK_RV rv;
int i;
.
.
memset(iv, 0, sizeof(iv));
memset(data, ‘A’, ((2*BUF_SZ)+5));
rv = C_EncryptInit(hSession, &encryptionMechanism, hEncryptionKey);
if (rv != CKR_OK) {
.
.
}
rv = C_SignInit(hSession, &signMechanism, hMacKey);
if (rv != CKR_OK) {
.
.
}
ulEncryptedDataLen = sizeof(encryptedData);
rv = C_SignEncryptUpdate(
hSession,
&data[0], BUF_SZ,
encryptedData, &ulEncryptedDataLen);
.
.
ulEncryptedDataLen = sizeof(encryptedData);
rv = C_SignEncryptUpdate(
hSession,
&data[BUF_SZ], BUF_SZ,
encryptedData, &ulEncryptedDataLen);
.
.
/*
* The last portion of the buffer needs to be handled with
* separate calls to deal with padding issues in ECB mode
*/
/* First, complete the signature on the buffer */
rv = C_SignUpdate(hSession, &data[BUF_SZ*2], 5);
.
.
ulMacLen = sizeof(MAC);
rv = C_SignFinal(hSession, MAC, &ulMacLen);
.
.

CK_DEFINE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)(
CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedPart,
CK_ULONG ulEncryptedPartLen,
CK_BYTE_PTR pPart,
CK_ULONG_PTR pulPartLen
);
C_DecryptVerifyUpdate continues a multiple-part combined decryption and verification operation, processing another data part. hSession is the session’s handle; pEncryptedPart points to the encrypted data; ulEncryptedPartLen is the length of the encrypted data; pPart points to the location that receives the recovered data; and pulPartLen points to the location that holds the length of the recovered data.
C_DecryptVerifyUpdate uses the convention described in Section 5.2 on producing output. If a C_DecryptVerifyUpdate call does not produce decrypted output (because an error occurs, or because pPart has the value NULL_PTR, or because pulPartLen is too small to hold the entire encrypted part output), then no plaintext is passed to the active verification operation.
Decryption and signature operations MUST both be active (they MUST have been initialized with C_DecryptInit and C_VerifyInit, respectively). This function may be called any number of times in succession, and may be interspersed with C_DecryptUpdate and C_VerifyUpdate calls.
Use of C_DecryptVerifyUpdate involves a pipelining issue that does not arise when using C_SignEncryptUpdate, the “inverse function” of C_DecryptVerifyUpdate. This is because when C_SignEncryptUpdate is called, precisely the same input is passed to both the active signing operation and the active encryption operation; however, when C_DecryptVerifyUpdate is called, the input passed to the active verifying operation is the output of the active decryption operation. This issue comes up only when the mechanism used for decryption performs padding.
In particular, envision a 24-byte ciphertext which was obtained by encrypting an 18-byte plaintext with DES in CBC mode with PKCS padding. Consider an application which will simultaneously decrypt this ciphertext and verify a signature on the original plaintext thereby obtained.
After initializing decryption and verification operations, the application passes the 24-byte ciphertext (3 DES blocks) into C_DecryptVerifyUpdate. C_DecryptVerifyUpdate returns exactly 16 bytes of plaintext, since at this point, Cryptoki doesn’t know if there’s more ciphertext coming, or if the last block of ciphertext held any padding. These 16 bytes of plaintext are passed into the active verification operation.
Since there is no more ciphertext, the application calls C_DecryptFinal. This tells Cryptoki that there’s no more ciphertext coming, and the call returns the last 2 bytes of plaintext. However, since the active decryption and verification operations are linked only through the C_DecryptVerifyUpdate call, these 2 bytes of plaintext are not passed on to the verification mechanism.
A call to C_VerifyFinal, therefore, would verify whether or not the signature supplied is a valid signature on the first 16 bytes of the plaintext, not on the entire plaintext. It is crucial that, before C_VerifyFinal is called, the last 2 bytes of plaintext get passed into the active verification operation via a C_VerifyUpdate call.
Because of this, it is critical that when an application uses a padded decryption mechanism with C_DecryptVerifyUpdate, it knows exactly how much plaintext has been passed into the active verification operation. Extreme caution is warranted when using a padded decryption mechanism with C_DecryptVerifyUpdate.
Return values: CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID.
Example:
#define BUF_SZ 512
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hDecryptionKey, hMacKey;
CK_BYTE iv[8];
CK_MECHANISM decryptionMechanism = {
CKM_DES_ECB, iv, sizeof(iv)
};
CK_MECHANISM verifyMechanism = {
CKM_DES_MAC, NULL_PTR, 0
};
CK_BYTE encryptedData[(2*BUF_SZ)+8];
CK_BYTE MAC[4];
CK_ULONG ulMacLen;
CK_BYTE data[BUF_SZ];
CK_ULONG ulDataLen, ulLastUpdateSize;
CK_RV rv;
.
.
memset(iv, 0, sizeof(iv));
memset(encryptedData, ‘A’, ((2*BUF_SZ)+8));
rv = C_DecryptInit(hSession, &decryptionMechanism, hDecryptionKey);
if (rv != CKR_OK) {
.
.
}
rv = C_VerifyInit(hSession, &verifyMechanism, hMacKey);
if (rv != CKR_OK){
.
.
}
ulDataLen = sizeof(data);
rv = C_DecryptVerifyUpdate(
hSession,
&encryptedData[0], BUF_SZ,
data, &ulDataLen);
.
.
ulDataLen = sizeof(data);
rv = C_DecryptVerifyUpdate(
hSession,
&encryptedData[BUF_SZ], BUF_SZ,
data, &uldataLen);
.
.
/*
* The last portion of the buffer needs to be handled with
* separate calls to deal with padding issues in ECB mode
*/
/* First, complete the decryption of the buffer */
ulLastUpdateSize = sizeof(data);
rv = C_DecryptUpdate(
hSession,
&encryptedData[BUF_SZ*2], 8,
data, &ulLastUpdateSize);
.
.
 Should have length 0 */
ulDataLen = sizeof(data)-ulLastUpdateSize;
rv = C_DecryptFinal(hSession, &data[ulLastUpdateSize], &ulDataLen);
if (rv != CKR_OK) {
.
.
}
/* Send last bit of plaintext to verification operation */
rv = C_VerifyUpdate(hSession, &data[BUF_SZ*2], 5);
if (rv != CKR_OK) {
.
.
}
rv = C_VerifyFinal(hSession, MAC, ulMacLen);
if (rv == CKR_SIGNATURE_INVALID) {
.
.
}
Cryptoki provides the following functions for key management:
CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey)(
CK_SESSION_HANDLE hSession
CK_MECHANISM_PTR pMechanism,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulCount,
CK_OBJECT_HANDLE_PTR phKey
);
C_GenerateKey generates a secret key or set of domain parameters, creating a new object. hSession is the session’s handle; pMechanism points to the generation mechanism; pTemplate points to the template for the new key or set of domain parameters; ulCount is the number of attributes in the template; phKey points to the location that receives the handle of the new key or set of domain parameters.
If the generation mechanism is for domain parameter generation, the CKA_CLASS attribute will have the value CKO_DOMAIN_PARAMETERS; otherwise, it will have the value CKO_SECRET_KEY.
Since the type of key or domain parameters to be generated is implicit in the generation mechanism, the template does not need to supply a key type. If it does supply a key type which is inconsistent with the generation mechanism, C_GenerateKey fails and returns the error code CKR_TEMPLATE_INCONSISTENT. The CKA_CLASS attribute is treated similarly.
If a call to C_GenerateKey cannot support the precise template supplied to it, it will fail and return without creating an object.
The object created by a successful call to C_GenerateKey will have its CKA_LOCAL attribute set to CK_TRUE.
Return values: CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN.
Example:
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hKey;
CK_MECHANISM mechanism = {
CKM_DES_KEY_GEN, NULL_PTR, 0
};
CK_RV rv;
.
.
rv = C_GenerateKey(hSession, &mechanism, NULL_PTR, 0, &hKey);
if (rv == CKR_OK) {
.
.
}
CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)(
CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_ATTRIBUTE_PTR pPublicKeyTemplate,
CK_ULONG ulPublicKeyAttributeCount,
CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
CK_ULONG ulPrivateKeyAttributeCount,
CK_OBJECT_HANDLE_PTR phPublicKey,
CK_OBJECT_HANDLE_PTR phPrivateKey
);
C_GenerateKeyPair generates a public/private key pair, creating new key objects. hSession is the session’s handle; pMechanism points to the key generation mechanism; pPublicKeyTemplate points to the template for the public key; ulPublicKeyAttributeCount is the number of attributes in the public-key template; pPrivateKeyTemplate points to the template for the private key; ulPrivateKeyAttributeCount is the number of attributes in the private-key template; phPublicKey points to the location that receives the handle of the new public key; phPrivateKey points to the location that receives the handle of the new private key.
Since the types of keys to be generated are implicit in the key pair generation mechanism, the templates do not need to supply key types. If one of the templates does supply a key type which is inconsistent with the key generation mechanism, C_GenerateKeyPair fails and returns the error code CKR_TEMPLATE_INCONSISTENT. The CKA_CLASS attribute is treated similarly.
If a call to C_GenerateKeyPair cannot support the precise templates supplied to it, it will fail and return without creating any key objects.
A call to C_GenerateKeyPair will never create just one key and return. A call can fail, and create no keys; or it can succeed, and create a matching public/private key pair.
The key objects created by a successful call to C_GenerateKeyPair will have their CKA_LOCAL attributes set to CK_TRUE.
Note carefully the order of the arguments to C_GenerateKeyPair. The last two arguments do not have the same order as they did in the original Cryptoki Version 1.0 document. The order of these two arguments has caused some unfortunate confusion.
Return values: CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN.
Example:
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
CK_MECHANISM mechanism = {
CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0
};
CK_ULONG modulusBits = 768;
CK_BYTE publicExponent[] = { 3 };
CK_BYTE subject[] = {...};
CK_BYTE id[] = {123};
CK_BBOOL true = CK_TRUE;
CK_ATTRIBUTE publicKeyTemplate[] = {
{CKA_ENCRYPT, &true, sizeof(true)},
{CKA_VERIFY, &true, sizeof(true)},
{CKA_WRAP, &true, sizeof(true)},
{CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)},
{CKA_PUBLIC_EXPONENT, publicExponent, sizeof (publicExponent)}
};
CK_ATTRIBUTE privateKeyTemplate[] = {
{CKA_TOKEN, &true, sizeof(true)},
{CKA_PRIVATE, &true, sizeof(true)},
{CKA_SUBJECT, subject, sizeof(subject)},
{CKA_ID, id, sizeof(id)},
{CKA_SENSITIVE, &true, sizeof(true)},
{CKA_DECRYPT, &true, sizeof(true)},
{CKA_SIGN, &true, sizeof(true)},
{CKA_UNWRAP, &true, sizeof(true)}
};
CK_RV rv;
rv = C_GenerateKeyPair(
hSession, &mechanism,
publicKeyTemplate, 5,
privateKeyTemplate, 8,
&hPublicKey, &hPrivateKey);
if (rv == CKR_OK) {
.
.
}
CK_DEFINE_FUNCTION(CK_RV, C_WrapKey)(
CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hWrappingKey,
CK_OBJECT_HANDLE hKey,
CK_BYTE_PTR pWrappedKey,
CK_ULONG_PTR pulWrappedKeyLen
);
C_WrapKey wraps (i.e., encrypts) a private or secret key. hSession is the session’s handle; pMechanism points to the wrapping mechanism; hWrappingKey is the handle of the wrapping key; hKey is the handle of the key to be wrapped; pWrappedKey points to the location that receives the wrapped key; and pulWrappedKeyLen points to the location that receives the length of the wrapped key.
C_WrapKey uses the convention described in Section 5.2 on producing output.
The CKA_WRAP attribute of the wrapping key, which indicates whether the key supports wrapping, MUST be CK_TRUE. The CKA_EXTRACTABLE attribute of the key to be wrapped MUST also be CK_TRUE.
If the key to be wrapped cannot be wrapped for some token-specific reason, despite its having its CKA_EXTRACTABLE attribute set to CK_TRUE, then C_WrapKey fails with error code CKR_KEY_NOT_WRAPPABLE. If it cannot be wrapped with the specified wrapping key and mechanism solely because of its length, then C_WrapKey fails with error code CKR_KEY_SIZE_RANGE.
C_WrapKey can be used in the following situations:
· To wrap any secret key with a public key that supports encryption and decryption.
· To wrap any secret key with any other secret key. Consideration MUST be given to key size and mechanism strength or the token may not allow the operation.
· To wrap a private key with any secret key.
Of course, tokens vary in which types of keys can actually be wrapped with which mechanisms.
To partition the wrapping keys so they can only wrap a subset of extractable keys the attribute CKA_WRAP_TEMPLATE can be used on the wrapping key to specify an attribute set that will be compared against the attributes of the key to be wrapped. If all attributes match according to the C_FindObject rules of attribute matching then the wrap will proceed. The value of this attribute is an attribute template and the size is the number of items in the template times the size of CK_ATTRIBUTE. If this attribute is not supplied then any template is acceptable. If an attribute is not present, it will not be checked. If any attribute mismatch occurs on an attempt to wrap a key then the function SHALL return CKR_KEY_HANDLE_INVALID.
Return Values: CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_HANDLE_INVALID, CKR_KEY_NOT_WRAPPABLE, CKR_KEY_SIZE_RANGE, CKR_KEY_UNEXTRACTABLE, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN, CKR_WRAPPING_KEY_HANDLE_INVALID, CKR_WRAPPING_KEY_SIZE_RANGE, CKR_WRAPPING_KEY_TYPE_INCONSISTENT.
Example:
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hWrappingKey, hKey;
CK_MECHANISM mechanism = {
CKM_DES3_ECB, NULL_PTR, 0
};
CK_BYTE wrappedKey[8];
CK_ULONG ulWrappedKeyLen;
CK_RV rv;
.
.
ulWrappedKeyLen = sizeof(wrappedKey);
rv = C_WrapKey(
hSession, &mechanism,
hWrappingKey, hKey,
wrappedKey, &ulWrappedKeyLen);
if (rv == CKR_OK) {
.
.
}
CK_DEFINE_FUNCTION(CK_RV, C_UnwrapKey)(
CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hUnwrappingKey,
CK_BYTE_PTR pWrappedKey,
CK_ULONG ulWrappedKeyLen,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulAttributeCount,
CK_OBJECT_HANDLE_PTR phKey
);
C_UnwrapKey unwraps (i.e. decrypts) a wrapped key, creating a new private key or secret key object. hSession is the session’s handle; pMechanism points to the unwrapping mechanism; hUnwrappingKey is the handle of the unwrapping key; pWrappedKey points to the wrapped key; ulWrappedKeyLen is the length of the wrapped key; pTemplate points to the template for the new key; ulAttributeCount is the number of attributes in the template; phKey points to the location that receives the handle of the recovered key.
The CKA_UNWRAP attribute of the unwrapping key, which indicates whether the key supports unwrapping, MUST be CK_TRUE.
The new key will have the CKA_ALWAYS_SENSITIVE attribute set to CK_FALSE, and the CKA_NEVER_EXTRACTABLE attribute set to CK_FALSE. The CKA_EXTRACTABLE attribute is by default set to CK_TRUE.
Some mechanisms may modify, or attempt to modify. the contents of the pMechanism structure at the same time that the key is unwrapped.
If a call to C_UnwrapKey cannot support the precise template supplied to it, it will fail and return without creating any key object.
The key object created by a successful call to C_UnwrapKey will have its CKA_LOCAL attribute set to CK_FALSE.
To partition the unwrapping keys so they can only unwrap a subset of keys the attribute CKA_UNWRAP_TEMPLATE can be used on the unwrapping key to specify an attribute set that will be added to attributes of the key to be unwrapped. If the attributes do not conflict with the user supplied attribute template, in ‘pTemplate’, then the unwrap will proceed. The value of this attribute is an attribute template and the size is the number of items in the template times the size of CK_ATTRIBUTE. If this attribute is not present on the unwrapping key then no additional attributes will be added. If any attribute conflict occurs on an attempt to unwrap a key then the function SHALL return CKR_TEMPLATE_INCONSISTENT.
Return values: CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_SIZE_RANGE, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, CKR_USER_NOT_LOGGED_IN, CKR_WRAPPED_KEY_INVALID, CKR_WRAPPED_KEY_LEN_RANGE.
Example:
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hUnwrappingKey, hKey;
CK_MECHANISM mechanism = {
CKM_DES3_ECB, NULL_PTR, 0
};
CK_BYTE wrappedKey[8] = {...};
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
CK_KEY_TYPE keyType = CKK_DES;
CK_BBOOL true = CK_TRUE;
CK_ATTRIBUTE template[] = {
{CKA_CLASS, &keyClass, sizeof(keyClass)},
{CKA_KEY_TYPE, &keyType, sizeof(keyType)},
{CKA_ENCRYPT, &true, sizeof(true)},
{CKA_DECRYPT, &true, sizeof(true)}
};
CK_RV rv;
.
.
rv = C_UnwrapKey(
hSession, &mechanism, hUnwrappingKey,
wrappedKey, sizeof(wrappedKey), template, 4, &hKey);
if (rv == CKR_OK) {
.
.
}
CK_DEFINE_FUNCTION(CK_RV, C_DeriveKey)(
CK_SESSION_HANDLE hSession,
CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hBaseKey,
CK_ATTRIBUTE_PTR pTemplate,
CK_ULONG ulAttributeCount,
CK_OBJECT_HANDLE_PTR phKey
);
C_DeriveKey derives a key from a base key, creating a new key object. hSession is the session’s handle; pMechanism points to a structure that specifies the key derivation mechanism; hBaseKey is the handle of the base key; pTemplate points to the template for the new key; ulAttributeCount is the number of attributes in the template; and phKey points to the location that receives the handle of the derived key.
The values of the CKA_SENSITIVE, CKA_ALWAYS_SENSITIVE, CKA_EXTRACTABLE, and CKA_NEVER_EXTRACTABLE attributes for the base key affect the values that these attributes can hold for the newly-derived key. See the description of each particular key-derivation mechanism in Section 5.16.2 for any constraints of this type.
If a call to C_DeriveKey cannot support the precise template supplied to it, it will fail and return without creating any key object.
The key object created by a successful call to C_DeriveKey will have its CKA_LOCAL attribute set to CK_FALSE.
Return values: CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_HANDLE_INVALID, CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN.
Example:
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hPublicKey, hPrivateKey, hKey;
CK_MECHANISM keyPairMechanism = {
CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0
};
CK_BYTE prime[] = {...};
CK_BYTE base[] = {...};
CK_BYTE publicValue[128];
CK_BYTE otherPublicValue[128];
CK_MECHANISM mechanism = {
CKM_DH_PKCS_DERIVE, otherPublicValue, sizeof(otherPublicValue)
};
CK_ATTRIBUTE pTemplate[] = {
CKA_VALUE, &publicValue, sizeof(publicValue)}
};
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
CK_KEY_TYPE keyType = CKK_DES;
CK_BBOOL true = CK_TRUE;
CK_ATTRIBUTE publicKeyTemplate[] = {
{CKA_PRIME, prime, sizeof(prime)},
{CKA_BASE, base, sizeof(base)}
};
CK_ATTRIBUTE privateKeyTemplate[] = {
{CKA_DERIVE, &true, sizeof(true)}
};
CK_ATTRIBUTE template[] = {
{CKA_CLASS, &keyClass, sizeof(keyClass)},
{CKA_KEY_TYPE, &keyType, sizeof(keyType)},
{CKA_ENCRYPT, &true, sizeof(true)},
{CKA_DECRYPT, &true, sizeof(true)}
};
CK_RV rv;
.
.
rv = C_GenerateKeyPair(
hSession, &keyPairMechanism,
publicKeyTemplate, 2,
privateKeyTemplate, 1,
&hPublicKey, &hPrivateKey);
if (rv == CKR_OK) {
rv = C_GetAttributeValue(hSession, hPublicKey, &pTemplate, 1);
if (rv == CKR_OK) {
/* Put other guy’s public value in otherPublicValue */
.
.
rv = C_DeriveKey(
hSession, &mechanism,
hPrivateKey, template, 4, &hKey);
if (rv == CKR_OK) {
.
.
}
}
}
Cryptoki provides the following functions for generating random numbers:
CK_DEFINE_FUNCTION(CK_RV, C_SeedRandom)(
CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pSeed,
CK_ULONG ulSeedLen
);
C_SeedRandom mixes additional seed material into the token’s random number generator. hSession is the session’s handle; pSeed points to the seed material; and ulSeedLen is the length in bytes of the seed material.
Return values: CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_ACTIVE, CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN.
Example: see C_GenerateRandom.
CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom)(
CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pRandomData,
CK_ULONG ulRandomLen
);
C_GenerateRandom generates random or pseudo-random data. hSession is the session’s handle; pRandomData points to the location that receives the random data; and ulRandomLen is the length in bytes of the random or pseudo-random data to be generated.
Return values: CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, CKR_OPERATION_ACTIVE, CKR_RANDOM_NO_RNG, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN.
Example:
CK_SESSION_HANDLE hSession;
CK_BYTE seed[] = {...};
CK_BYTE randomData[] = {...};
CK_RV rv;
.
.
rv = C_SeedRandom(hSession, seed, sizeof(seed));
if (rv != CKR_OK) {
.
.
}
rv = C_GenerateRandom(hSession, randomData, sizeof(randomData));
if (rv == CKR_OK) {
.
.
}
Cryptoki provides the following functions for managing parallel execution of cryptographic functions. These functions exist only for backwards compatibility.
CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionStatus)(
CK_SESSION_HANDLE hSession
);
In previous versions of Cryptoki, C_GetFunctionStatus obtained the status of a function running in parallel with an application. Now, however, C_GetFunctionStatus is a legacy function which should simply return the value CKR_FUNCTION_NOT_PARALLEL.
Return values: CKR_CRYPTOKI_NOT_INITIALIZED, CKR_FUNCTION_FAILED, CKR_FUNCTION_NOT_PARALLEL, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_CLOSED.
CK_DEFINE_FUNCTION(CK_RV, C_CancelFunction)(
CK_SESSION_HANDLE hSession
);
In previous versions of Cryptoki, C_CancelFunction cancelled a function running in parallel with an application. Now, however, C_CancelFunction is a legacy function which should simply return the value CKR_FUNCTION_NOT_PARALLEL.
Return values: CKR_CRYPTOKI_NOT_INITIALIZED, CKR_FUNCTION_FAILED, CKR_FUNCTION_NOT_PARALLEL, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_SESSION_HANDLE_INVALID, CKR_SESSION_CLOSED.
Cryptoki sessions can use function pointers of type CK_NOTIFY to notify the application of certain events.
Cryptographic functions (i.e., any functions falling under one of these categories: encryption functions; decryption functions; message digesting functions; signing and MACing functions; functions for verifying signatures and MACs; dual-purpose cryptographic functions; key management functions; random number generation functions) executing in Cryptoki sessions can periodically surrender control to the application who called them if the session they are executing in had a notification callback function associated with it when it was opened. They do this by calling the session’s callback with the arguments (hSession, CKN_SURRENDER, pApplication), where hSession is the session’s handle and pApplication was supplied to C_OpenSession when the session was opened. Surrender callbacks should return either the value CKR_OK (to indicate that Cryptoki should continue executing the function) or the value CKR_CANCEL (to indicate that Cryptoki should abort execution of the function). Of course, before returning one of these values, the callback function can perform some computation, if desired.
A typical use of a surrender callback might be to give an application user feedback during a lengthy key pair generation operation. Each time the application receives a callback, it could display an additional “.” to the user. It might also examine the keyboard’s activity since the last surrender callback, and abort the key pair generation operation (probably by returning the value CKR_CANCEL) if the user hit <ESCAPE>.
A Cryptoki library is not required to make any surrender callbacks.
Library vendors can also define additional types of callbacks. Because of this extension capability, application-supplied notification callback routines should examine each callback they receive, and if they are unfamiliar with the type of that callback, they should immediately give control back to the library by returning with the value CKR_OK.
An implementation is a conforming implementation if it meets the conditions specified in one or more server profiles specified in [PKCS #11-Prof].
If a PKCS #11 implementation claims support for a particular profile, then the implementation SHALL conform to all normative statements within the clauses specified for that profile and for any subclauses to each of those clauses.
The following individuals have participated in the creation of this specification and are gratefully acknowledged:
Participants:
Gil Abel, Athena Smartcard Solutions, Inc.
Warren Armstrong, QuintessenceLabs
Jeff Bartell, Semper Foris Solutions LLC
Peter Bartok, Venafi, Inc.
Anthony Berglas, Cryptsoft
Joseph Brand, Semper Fortis Solutions LLC
Kelley Burgin, National Security Agency
Robert Burns, Thales e-Security
Wan-Teh Chang, Google Inc.
Hai-May Chao, Oracle
Janice Cheng, Vormetric, Inc.
Sangrae Cho, Electronics and Telecommunications Research Institute (ETRI)
Doron Cohen, SafeNet, Inc.
Fadi Cotran, Futurex
Tony Cox, Cryptsoft
Christopher Duane, EMC
Chris Dunn, SafeNet, Inc.
Valerie Fenwick, Oracle
Terry Fletcher, SafeNet, Inc.
Susan Gleeson, Oracle
Sven Gossel, Charismathics
John Green, QuintessenceLabs
Robert Griffin, EMC
Paul Grojean, Individual
Peter Gutmann, Individual
Dennis E. Hamilton, Individual
Thomas Hardjono, M.I.T.
Tim Hudson, Cryptsoft
Gershon Janssen, Individual
Seunghun Jin, Electronics and Telecommunications Research Institute (ETRI)
Wang Jingman, Feitan Technologies
Andrey Jivsov, Symantec Corp.
Mark Joseph, P6R
Stefan Kaesar, Infineon Technologies
Greg Kazmierczak, Wave Systems Corp.
Mark Knight, Thales e-Security
Darren Krahn, Google Inc.
Alex Krasnov, Infineon Technologies AG
Dina Kurktchi-Nimeh, Oracle
Mark Lambiase, SecureAuth Corporation
Lawrence Lee, GoTrust Technology Inc.
John Leiseboer, QuintessenceLabs
Sean Leon, Infineon Technologies
Geoffrey Li, Infineon Technologies
Howie Liu, Infineon Technologies
Hal Lockhart, Oracle
Robert Lockhart, Thales e-Security
Dale Moberg, Axway Software
Darren Moffat, Oracle
Valery Osheter, SafeNet, Inc.
Sean Parkinson, EMC
Rob Philpott, EMC
Mark Powers, Oracle
Ajai Puri, SafeNet, Inc.
Robert Relyea, Red Hat
Saikat Saha, Oracle
Subhash Sankuratripati, NetApp
Anthony Scarpino, Oracle
Johann Schoetz, Infineon Technologies AG
Rayees Shamsuddin, Wave Systems Corp.
Radhika Siravara, Oracle
Brian Smith, Mozilla Corporation
David Smith, Venafi, Inc.
Ryan Smith, Futurex
Jerry Smith, US Department of Defense (DoD)
Oscar So, Oracle
Graham Steel, Cryptosense
Michael Stevens, QuintessenceLabs
Michael StJohns, Individual
Jim Susoy, P6R
Sander Temme, Thales e-Security
Kiran Thota, VMware, Inc.
Walter-John Turnes, Gemini Security Solutions, Inc.
Stef Walter, Red Hat
James Wang, Vormetric
Jeff Webb, Dell
Peng Yu, Feitian Technologies
Magda Zdunkiewicz, Cryptsoft
Chris Zimman, Individual
.
The following definitions can be found in the appropriate header file. Also, refer [PKCS11_Curr] and [PKCS11_HIST] for additional definitions.
/*
* Copyright © Oasis Open 2013. All right reserved.
* OASIS trademark, IPR and other policies apply.
* http://www.oasis-open.org/policies-guidelines/ipr
*/
#define CK_INVALID_HANDLE 0UL
#define CKN_SURRENDER 0UL
#define CK_UNAVAILABLE_INFORMATION (~0UL)
#define CK_EFFECTIVELY_INFINITE 0UL
#define CKF_DONT_BLOCK 1
#define CKF_ARRAY_ATTRIBUTE 0x40000000UL
#define CKU_SO 0UL
#define CKU_USER 1UL
#define CKU_CONTEXT_SPECIFIC 2UL
#define CKS_RO_PUBLIC_SESSION 0UL
#define CKS_RO_USER_FUNCTIONS 1UL
#define CKS_RW_PUBLIC_SESSION 2UL
#define CKS_RW_USER_FUNCTIONS 3UL
#define CKS_RW_SO_FUNCTIONS 4UL
#define CKO_DATA 0x00000000UL
#define CKO_CERTIFICATE 0x00000001UL
#define CKO_PUBLIC_KEY 0x00000002UL
#define CKO_PRIVATE_KEY 0x00000003UL
#define CKO_SECRET_KEY 0x00000004UL
#define CKO_HW_FEATURE 0x00000005UL
#define CKO_DOMAIN_PARAMETERS 0x00000006UL
#define CKO_MECHANISM 0x00000007UL
#define CKO_VENDOR_DEFINED 0x80000000UL
#define CKH_MONOTONIC_COUNTER 0x00000001UL
#define CKH_CLOCK 0x00000002UL
#define CKH_USER_INTERFACE 0x00000003UL
#define CKH_VENDOR_DEFINED 0x80000000UL
#define CKA_CLASS 0x00000000UL
#define CKA_TOKEN 0x00000001UL
#define CKA_PRIVATE 0x00000002UL
#define CKA_LABEL 0x00000003UL
#define CKA_APPLICATION 0x00000010UL
#define CKA_VALUE 0x00000011UL
#define CKA_OBJECT_ID 0x00000012UL
#define CKA_CERTIFICATE_TYPE 0x00000080UL
#define CKA_ISSUER 0x00000081UL
#define CKA_SERIAL_NUMBER 0x00000082UL
#define CKA_AC_ISSUER 0x00000083UL
#define CKA_OWNER 0x00000084UL
#define CKA_ATTR_TYPES 0x00000085UL
#define CKA_TRUSTED 0x00000086UL
#define CKA_CERTIFICATE_CATEGORY 0x00000087UL
#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088UL
#define CKA_URL 0x00000089UL
#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008AUL
#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008BUL
#define CKA_NAME_HASH_ALGORITHM 0x0000008CUL
#define CKA_CHECK_VALUE 0x00000090UL
#define CKA_KEY_TYPE 0x00000100UL
#define CKA_SUBJECT 0x00000101UL
#define CKA_ID 0x00000102UL
#define CKA_SENSITIVE 0x00000103UL
#define CKA_ENCRYPT 0x00000104UL
#define CKA_DECRYPT 0x00000105UL
#define CKA_WRAP 0x00000106UL
#define CKA_UNWRAP 0x00000107UL
#define CKA_SIGN 0x00000108UL
#define CKA_SIGN_RECOVER 0x00000109UL
#define CKA_VERIFY 0x0000010AUL
#define CKA_VERIFY_RECOVER 0x0000010BUL
#define CKA_DERIVE 0x0000010CUL
#define CKA_START_DATE 0x00000110UL
#define CKA_END_DATE 0x00000111UL
#define CKA_MODULUS 0x00000120UL
#define CKA_MODULUS_BITS 0x00000121UL
#define CKA_PUBLIC_EXPONENT 0x00000122UL
#define CKA_PRIVATE_EXPONENT 0x00000123UL
#define CKA_PRIME_1 0x00000124UL
#define CKA_PRIME_2 0x00000125UL
#define CKA_EXPONENT_1 0x00000126UL
#define CKA_EXPONENT_2 0x00000127UL
#define CKA_COEFFICIENT 0x00000128UL
#define CKA_PRIME 0x00000130UL
#define CKA_SUBPRIME 0x00000131UL
#define CKA_BASE 0x00000132UL
#define CKA_PRIME_BITS 0x00000133UL
#define CKA_SUBPRIME_BITS 0x00000134UL
#define CKA_VALUE_BITS 0x00000160UL
#define CKA_VALUE_LEN 0x00000161UL
#define CKA_EXTRACTABLE 0x00000162UL
#define CKA_LOCAL 0x00000163UL
#define CKA_NEVER_EXTRACTABLE 0x00000164UL
#define CKA_ALWAYS_SENSITIVE 0x00000165UL
#define CKA_KEY_GEN_MECHANISM 0x00000166UL
#define CKA_MODIFIABLE 0x00000170UL
#define CKA_COPYABLE 0x00000171UL
#define CKA_DESTROYABLE 0x00000172UL
#define CKA_ECDSA_PARAMS 0x00000180UL
#define CKA_EC_PARAMS 0x00000180UL
#define CKA_EC_POINT 0x00000181UL
#define CKA_SECONDARY_AUTH 0x00000200UL /* Deprecated */
#define CKA_AUTH_PIN_FLAGS 0x00000201UL /* Deprecated */
#define CKA_ALWAYS_AUTHENTICATE 0x00000202UL
#define CKA_WRAP_WITH_TRUSTED 0x00000210UL
#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211UL)
#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212UL)
#define CKA_HW_FEATURE_TYPE 0x00000300UL
#define CKA_RESET_ON_INIT 0x00000301UL
#define CKA_HAS_RESET 0x00000302UL
#define CKA_PIXEL_X 0x00000400UL
#define CKA_PIXEL_Y 0x00000401UL
#define CKA_RESOLUTION 0x00000402UL
#define CKA_CHAR_ROWS 0x00000403UL
#define CKA_CHAR_COLUMNS 0x00000404UL
#define CKA_COLOR 0x00000405UL
#define CKA_BITS_PER_PIXEL 0x00000406UL
#define CKA_CHAR_SETS 0x00000480UL
#define CKA_ENCODING_METHODS 0x00000481UL
#define CKA_MIME_TYPES 0x00000482UL
#define CKA_MECHANISM_TYPE 0x00000500UL
#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501UL
#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502UL
#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503UL
#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600UL)
#define CKA_VENDOR_DEFINED 0x80000000UL
#define CKR_OK 0x00000000UL
#define CKR_CANCEL 0x00000001UL
#define CKR_HOST_MEMORY 0x00000002UL
#define CKR_SLOT_ID_INVALID 0x00000003UL
#define CKR_GENERAL_ERROR 0x00000005UL
#define CKR_FUNCTION_FAILED 0x00000006UL
#define CKR_ARGUMENTS_BAD 0x00000007UL
#define CKR_NO_EVENT 0x00000008UL
#define CKR_NEED_TO_CREATE_THREADS 0x00000009UL
#define CKR_CANT_LOCK 0x0000000AUL
#define CKR_ATTRIBUTE_READ_ONLY 0x00000010UL
#define CKR_ATTRIBUTE_SENSITIVE 0x00000011UL
#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012UL
#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013UL
#define CKR_COPY_PROHIBITED 0x0000001AUL
#define CKR_ACTION_PROHIBITED 0x0000001BUL
#define CKR_DATA_INVALID 0x00000020UL
#define CKR_DATA_LEN_RANGE 0x00000021UL
#define CKR_DEVICE_ERROR 0x00000030UL
#define CKR_DEVICE_MEMORY 0x00000031UL
#define CKR_DEVICE_REMOVED 0x00000032UL
#define CKR_ENCRYPTED_DATA_INVALID 0x00000040UL
#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041UL
#define CKR_FUNCTION_CANCELED 0x00000050UL
#define CKR_FUNCTION_NOT_PARALLEL 0x00000051UL
#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054UL
#define CKR_KEY_HANDLE_INVALID 0x00000060UL
#define CKR_KEY_SIZE_RANGE 0x00000062UL
#define CKR_KEY_TYPE_INCONSISTENT 0x00000063UL
#define CKR_KEY_NOT_NEEDED 0x00000064UL
#define CKR_KEY_CHANGED 0x00000065UL
#define CKR_KEY_NEEDED 0x00000066UL
#define CKR_KEY_INDIGESTIBLE 0x00000067UL
#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068UL
#define CKR_KEY_NOT_WRAPPABLE 0x00000069UL
#define CKR_KEY_UNEXTRACTABLE 0x0000006AUL
#define CKR_MECHANISM_INVALID 0x00000070UL
#define CKR_MECHANISM_PARAM_INVALID 0x00000071UL
#define CKR_OBJECT_HANDLE_INVALID 0x00000082UL
#define CKR_OPERATION_ACTIVE 0x00000090UL
#define CKR_OPERATION_NOT_INITIALIZED 0x00000091UL
#define CKR_PIN_INCORRECT 0x000000A0UL
#define CKR_PIN_INVALID 0x000000A1UL
#define CKR_PIN_LEN_RANGE 0x000000A2UL
#define CKR_PIN_EXPIRED 0x000000A3UL
#define CKR_PIN_LOCKED 0x000000A4UL
#define CKR_SESSION_CLOSED 0x000000B0UL
#define CKR_SESSION_COUNT 0x000000B1UL
#define CKR_SESSION_HANDLE_INVALID 0x000000B3UL
#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4UL
#define CKR_SESSION_READ_ONLY 0x000000B5UL
#define CKR_SESSION_EXISTS 0x000000B6UL
#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7UL
#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8UL
#define CKR_SIGNATURE_INVALID 0x000000C0UL
#define CKR_SIGNATURE_LEN_RANGE 0x000000C1UL
#define CKR_TEMPLATE_INCOMPLETE 0x000000D0UL
#define CKR_TEMPLATE_INCONSISTENT 0x000000D1UL
#define CKR_TOKEN_NOT_PRESENT 0x000000E0UL
#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1UL
#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2UL
#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0UL
#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1UL
#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2UL
#define CKR_USER_ALREADY_LOGGED_IN 0x00000100UL
#define CKR_USER_NOT_LOGGED_IN 0x00000101UL
#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102UL
#define CKR_USER_TYPE_INVALID 0x00000103UL
#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104UL
#define CKR_USER_TOO_MANY_TYPES 0x00000105UL
#define CKR_WRAPPED_KEY_INVALID 0x00000110UL
#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112UL
#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113UL
#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114UL
#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115UL
#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120UL
#define CKR_RANDOM_NO_RNG 0x00000121UL
#define CKR_DOMAIN_PARAMS_INVALID 0x00000130UL
#define CKR_CURVE_NOT_SUPPORTED 0x00000140UL
#define CKR_BUFFER_TOO_SMALL 0x00000150UL
#define CKR_SAVED_STATE_INVALID 0x00000160UL
#define CKR_INFORMATION_SENSITIVE 0x00000170UL
#define CKR_STATE_UNSAVEABLE 0x00000180UL
#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190UL
#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191UL
#define CKR_MUTEX_BAD 0x000001A0UL
#define CKR_MUTEX_NOT_LOCKED 0x000001A1UL
#define CKR_FUNCTION_REJECTED 0x00000200UL
#define CKR_VENDOR_DEFINED 0x80000000UL
#define CK_CERTIFICATE_CATEGORY_UNSPECIFIED 0UL
#define CK_CERTIFICATE_CATEGORY_TOKEN_USER 1UL
#define CK_CERTIFICATE_CATEGORY_AUTHORITY 2UL
#define CK_CERTIFICATE_CATEGORY_OTHER_ENTITY 3UL
#define CK_SECURITY_DOMAIN_UNSPECIFIED 0UL
#define CK_SECURITY_DOMAIN_MANUFACTURER 1UL
#define CK_SECURITY_DOMAIN_OPERATOR 2UL
#define CK_SECURITY_DOMAIN_THIRD_PARTY 3UL
|
Revision |
Date |
Editor |
Changes Made |
|
wd01 |
Apr 30 2013 |
Chris Zimman |
Initial import into OASIS template |
|
wd02 |
July 7 2013 |
Chris Zimman |
Move explanatory material to PKCS #11 Usage Guide v2.40 wd02 |
|
wd03 |
Aug 16 2013 |
Chris Zimman |
Incorporation of recent ballot items |
|
wd04 |
Oct 1 2013 |
Chris Zimman |
Incorporation of ballot items, prep for Committee Specification Draft promotion |
|
wd05 |
Oct 7 2013 |
Chris Zimman |
Typo correction and proof. This is the candidate for promotion to Committee Specification Draft. |
|
wd06 |
Oct 27 2013 |
Robert Griffin |
Final participant list and other editorial changes for Committee Specification Draft |
|
csd01 |
Oct 30 2013 |
OASIS |
Committee Specification Draft |
|
wd07 |
Feb 17 2014 |
Chris Zimman |
Incorporation of comments and changes from public feedback and review |
|
wd08 |
Feb 27 2014 |
Chris Zimman |
Incorporation of comments and changes from public feedback and review |
|
csd02 |
Apr 23 2014 |
OASIS |
Committee Specification Draft |
|
wd09 |
May 2 2014 |
Chris Zimman |
Incorporated changes from PKCS 11 TC face-to-face meeting |
|
wd10 |
Jul 2 2014 |
Chris Zimman |
Corrected manifest constants |
|
csd03 |
Jul 16 2014 |
OASIS |
Committee Specification Draft |
|
csd03a |
Sep 3 2014 |
Robert Griffin |
Updated revision history and participant list in preparation for Committee Specification ballot |
|
wd11 |
Nov 3 2014 |
Robert Griffin |
Editorial corrections |


Module Texture.TextureManager
TextureManager allows to mount a texture atlas as a logical resource path.
That means that calling TextureManager.getTexture() makes transparent the load of a real texture or of a subtexture of a texture atlas.
That allows to create code that doesn't depend on how data is packed. A use case is to always call TextureManager.getTexture() and, depending on how data is packed, add only at initialization phase a list of TextureManager.mountAtlas calls.
This list of atlas resources could be moreover defined by external data
Functions
| mountAtlas (mountDir, atlas) | Mount a texture atlas as logica resource at a specific path. |
| unmountAtlas (mountDir, atlas) | Unmount an atlas from given path |
| getTexture (fileName, useCache) | Returns a texture given a fileName. |
| clearCache (texture) | Remove a texture from the cache. |
Tables
| __atlasResources | used to store all the mounted textureAtlases |
| __textureCache | used to cache the textures stored into the TextureAtlases |
Functions
- mountAtlas (mountDir, atlas)
-
Mount a texture atlas as logica resource at a specific path.
It's possible to mount the same atlas at different paths.
It's possible to mount multiple atlas at same path.
Parameters:
- mountDir the path where to mount the atlas
- atlas the texture atlas to be mounted
- unmountAtlas (mountDir, atlas)
-
Unmount an atlas from given path
Parameters:
- mountDir the path where to unmount the atlas
- atlas the texture atlas to be unmounted
- getTexture (fileName, useCache)
-
Returns a texture given a fileName. The texture can be a physical resource or a subtexture
obtained from a texture atlas.
Textures not stored in mounted atlas are loaded through Assets.getText internal call
Parameters:
- fileName name of the texture to be retrieved
- useCache if defined override default Assets.__defaultCacheTexture value
- clearCache (texture)
-
Remove a texture from the cache. If texture is nil, clears the whole texture cache.
It calls also Assets.clearCache method
If nil the whole cache is cleared
Parameters:
- texture texture path or concrete resource to be removed from cache.


Bill Gates
Resume
Bill Gates is a technologist, business leader, and philanthropist. He grew up in Seattle, Washington, with an amazing and supportive family who encouraged his interest in computers at an early age. He dropped out of college to start Microsoft with his childhood friend Paul Allen. Today, Bill co-chairs the Bill & Melinda Gates Foundation with Melinda French Gates, where he works to give his wealth back to society. Bill grew up in Seattle with his two sisters. His late father, William H. Gates Sr., was a Seattle attorney and one of the co-chairs of the Bill & Melinda Gates Foundation. His late mother, Mary Gates, was a schoolteacher, University of Washington regent, and chairwoman of United Way International. Bill has three children.
-
1955
Born Seattle, WA.
-
1967
Enrolled at Lakeside School. First used computer.
-
1968
Began programming with Paul Allen in the computer center.
-
1973
Entered Harvard University.
-
1975
Started Micro-Soft with Paul Allen in Albuquerque, NM.
-
1976
Changed company name to Microsoft.
-
1979
Microsoft moved to Washington State.
-
1985
Windows 1.0 launched.
-
1995
Windows 95 launched
-
2000
Assumed role of Chief Software Architect, as Steve Ballmer assumed role of Microsoft CEO.
-
2008
Left his daily job at Microsoft.
-
2014
Stepped down as chairman. Remained on the board and began serving as technology advisor.
-
Present
Currently having a chill life :)
Bill and Melinda Gates Foundation
These days Bill focuses most of his time on the work he is doing through his foundation. People are often surprised to hear him say that this work has a lot in common with his work at Microsoft. In both cases, he gets to bring together smart people and collaborate with them to solve big, tough problems. Bill is gratified to know that the foundation and its many partners are helping people all over the world live healthier, more productive lives.
-
2000
Bill and Melinda officially established the foundation. They also announced the first round of Gates Millennium Scholars, part of a $1 billion effort to help 20,000 young people afford college over the next two decades.
-
2002
The foundation completed efforts to help install 47,000 computers in 11,000 libraries in all 50 states. Ninety-five percent of libraries have computers with Internet access, up from 27 percent in 1996.
-
2006
Warren Buffett pledged the bulk of his wealth to the foundation.
-
2010
Bill and Melinda challenged the global health community to declare this the Decade of Vaccines. They pledged $10 billion over the next 10 years to help research, develop, and deliver vaccines for the world’s poorest countries.
-
2008
Left his daily job at Microsoft.
-
2013
Bill helped launch a $5.5 billion effort to eradicate polio by 2018. India was certified polio-free by the World Health Organization, leaving only three countries that have never been free of the disease.
-
2015
Bill announced the formation of the Child Health and Mortality Prevention Surveillance Network (CHAMPS), a network of disease surveillance sites in developing countries, to help prevent childhood deaths.
-
2017
The Bill & Melinda Gates Foundation committed $300 million to helping farmers in Africa and Asia cope with climate change.
-
2018
Bill shared the stage with a beaker of poop at the Reinvented Toilet Expo in Beijing. His “co-star” helped draw attention to a serious problem that kills more than 500,00 people every year: poor sanitation


POSSIBLE WORLDS (2000) / **
Directed by Robert Lepage. Screenplay by Lepage and John Mighton. Starring Tom McCamus, Tilda Swinton, Sean McCann. Running time: 93 minutes. Rated PG by the MFCB. Reviewed on October 28th, 2001.
By SHANNON PATRICK SULLIVAN
Synopsis: Two police officers investigate the murder of George Barber (McCamus), whose brain has been stolen. Meanwhile, George apparently lives on in a number of "possible worlds", where George is the same man but others are vastly different, including his perpetual lover, Joyce (Swinton). What is the nature of George's possible worlds, and how do these relate to his apparent murder?
Review: "Possible Worlds" is an interesting but ultimately unsuccessful exploration of the concept of "parallel universes". Profound questions are raised, but are sadly tangled in a weak, unsatisfying story. As the only constant in each of the "worlds", George should be a strong focal character, an anchor for the audience. Unfortunately, he is a virtual spectre, gliding through the movie with little trace of personality. The same cannot be said of Joyce, in any of her incarnations, a role to which Swinton brings strength and evenness. But each Joyce is so prickly and abrasive that it is difficult to relate to her; consequently, the audience is left without anyone to care for. And while there is a wonderfully ethereal aura pervading "Possible Worlds", Lepage is unable to find a balance in this. The result is that the film frequently feels too slow, even boring. Attempts to spice things up by injecting comical scenes with the police officers are failures too, because the contrast is too jarring, and the humour feeble. And while it is understandable that Mighton leaves unanswered the questions he raises, it is less acceptable that entire plot points go unanswered -- what, for example, was the significance of a man found drowned in a room with no water? And this pales in comparison with the film's farcical ending, which is right out of a Hollywood B-movie.
Copyright © 2001 Shannon Patrick Sullivan. Archived at The Popcorn Gallery, http://www.physics.mun.ca/~sps/movies.html
| Shannon Patrick Sullivan |<EMAIL_ADDRESS>| +---------------------------------+---------------------------------+ / Doctor Who: A Brief History of Time (Travel) go.to/drwho-history \ \__ We are all in the gutter but some of us are looking at the stars __/
========== X-RAMR-ID: 29371 X-Language: en X-RT-SourceID: 886 X-RT-AuthorID: 1699 X-RT-RatingText: 2/4
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Preparation time
30 mins to 1 hour
Cooking time
30 mins to 1 hour
Serves
Serves 12
Dietary
This posh take on a Seventies' classic brings a retro dish bang up to date. Just add friends.
Lightly grease a 24cm/9½in square cake tin with butter. Line the base and sides with baking parchment.
For the pineapple sugar syrup, use two cookie cutters to make the outside edges and inside edges of each pineapple ring a uniform shape, alternatively trim them using a sharp knife. You need 4-5 pineapple rings.
Pour 500ml/18fl oz water into a large saucepan and add the caster sugar, vanilla pods, cinnamon stick, star anise and bay leaves. Bring to the boil, then add the pineapple rings and reduce the heat until the mixture is just simmering. Continue to simmer for 15-20 minutes, or until the pineapple is tender. Set the pan aside until the contents have completely cooled.
For the topping, put the butter and dark brown sugar in a large bowl. Using an electric whisk, beat them until fluffy, then stir in the dates, black peppercorns and the rum (if using).
Drain the cooled pineapple rings and arrange them into the bottom of the cake tin. Spread the topping mixture over the pineapple rings in an even layer.
For the cake, preheat the oven to 180C/350F/Gas 4.
In a clean mixing bowl, beat together the butter and sugar until fluffy using an electric whisk. Add the flour, baking powder, eggs, vanilla seeds and the rum, if using, then whisk again until just combined.
Spoon the cake mixture into the cake tin and smooth the top using a palette knife. Bake for 45 minutes, or until a skewer inserted into the centre of the cake comes out clean. Remove from the oven and set aside to cool for 10-15 minutes.
When cooled, turn the pineapple upside-down cake out onto a serving plate and remove the baking parchment.
For the toffee sauce, melt all of the toffee sauce ingredients together in a small saucepan over a low heat. Increase the heat until the mixture is boiling, then remove the pan from the heat.
For the coconut cream, in a mixing bowl, whisk together the chilled coconut cream and the caster sugar until soft peaks form when the whisk is removed.
To serve, slice the pineapple upside-down cake. Place each slice onto a serving plate, then drizzle over a little toffee sauce. Place a dollop of coconut cream alongside (if using), then sprinkle over a little lime zest.