/** Return a string with the printed digest of the given key file, or NULL if an error occurred. */ char* GetPubkeyDigest(const char* pubkey) { unsigned char digest[EVP_MAX_MD_SIZE + 1]; RSA* key = NULL; char* buffer = xmalloc(EVP_MAX_MD_SIZE * 4); key = LoadPublicKey(pubkey); if (NULL == key) { return NULL; } HashPubKey(key, digest, CF_DEFAULT_DIGEST); HashPrintSafe(CF_DEFAULT_DIGEST, digest, buffer); return buffer; }
/// <summary> /// Authenticates cartridge by verifying its certificate and its signature of a random token. /// </summary> /// <param name="ucCartridgeNum">The cartridge number.</param> /// <param name="aucPubKS">Stratasys public key.</param> /// <param name="aucIdd">The tag identification data (output parameter).</param> /// <param name="usIddLength">The tag identification data length (output parameter).</param> /// <param name="uiCurrentVolume">The tag current volume (output parameter).</param> /// <returns>0 on success, non-zero for failures.</returns> int MaterialMonitor::AuthenticateCartridge(unsigned char ucCartridgeNum, const unsigned char *aucPubKS, unsigned char *aucIdd, unsigned short *usIddLength, unsigned int *uiCurrentVolume) { UniqueLock uniqueLock(m_mtx); int returnValue = IDTLIB_SUCCESS; if (aucPubKS == NULL && m_pubKS == NULL) { returnValue = INVALID_HOST_KEY; LOG_EXT(LEVEL_ERROR, "Invalid host key (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } if (aucIdd == NULL || usIddLength == NULL || uiCurrentVolume == NULL) { returnValue = AUTHENTICATE_NULL_PARAMS; LOG_EXT(LEVEL_ERROR, "Invalid parameters (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } if (!m_bInitialized) { returnValue = HW_NOT_INITIALIZED; LOG_EXT(LEVEL_ERROR, "Hardware not initialized (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } try { LOG_EXT(LEVEL_INFO, "Cartridge #" << (unsigned short)ucCartridgeNum << " authentication started:"); LOG_EXT(LEVEL_INFO, "Reset cartridge #"<< (unsigned short)ucCartridgeNum << " info..."); int returnValue = ResetCartridgeInfo(ucCartridgeNum); if (returnValue != IDTLIB_SUCCESS) { LOG_EXT(LEVEL_ERROR, "Error resetting cartridge #"<< (unsigned short)ucCartridgeNum << " info (number of cartridges: " << (unsigned short)m_ucCartridgesCount << ", error code 0x" << hex << (short)returnValue << ")."); return returnValue; } LOG_EXT(LEVEL_INFO, "Switching to cartridge #"<< (unsigned short)ucCartridgeNum << "..."); returnValue = m_tagAdapter->SwitchToCartridge(ucCartridgeNum); if (returnValue != IDTLIB_SUCCESS) { LOG_EXT(LEVEL_ERROR, "Error switching to cartridge #"<< (unsigned short)ucCartridgeNum << " (number of cartridges: " << (unsigned short)m_ucCartridgesCount << ", error code 0x" << hex << (short)returnValue << ")."); return returnValue; } LOG_EXT(LEVEL_INFO, "Reading ID certificate..."); unsigned char aucBuffer[CERTIFICATE_SIZE]; memset(aucBuffer, 0, sizeof(aucBuffer)); returnValue = ReadIDCertificate(aucBuffer); if (returnValue != IDTLIB_SUCCESS) { LOG_EXT(LEVEL_ERROR, "Error reading ID certificate (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } bool isEmpty = m_tagAdapter->IsCertificateEmpty(aucBuffer); if (isEmpty) { returnValue = EMPTY_CERTIFICATE_FILE; LOG_EXT(LEVEL_ERROR, "Tag is blank (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } LOG_EXT(LEVEL_DEBUG, "Extracting cartridge #" << (unsigned short)ucCartridgeNum << " public key..."); IDCertificate *certificate = new IDCertificate(); unsigned short certificateSize; try { certificateSize = (unsigned short)certificate->Decode(aucBuffer); } catch (exception& e) { delete certificate; returnValue = INVALID_CERTIFICATE_FILE; LOG_EXT(LEVEL_ERROR, "Invalid certificate (error code 0x" << hex << (short)returnValue << "): " << e.what() << "."); return returnValue; } *usIddLength = certificateSize - SIGNATURE_SIZE - PUBLIC_KEY_SIZE; memcpy(aucIdd, aucBuffer, *usIddLength); ECDSA<EC2N, SHA256>::PublicKey* pubKS; if (aucPubKS != NULL) { pubKS = LoadPublicKey(aucPubKS); if (pubKS == NULL) { delete certificate; return INVALID_HOST_KEY; } } else { pubKS = m_pubKS; } LOG_EXT(LEVEL_INFO, "Verifying ID certificate..."); SetVerifier(pubKS); pthread_t verifierThread; VerifyParameters* verifyParameters = CreateVerifyParameters( m_veriferS, aucBuffer, certificateSize - SIGNATURE_SIZE, aucBuffer + (certificateSize - SIGNATURE_SIZE), SIGNATURE_SIZE); CreateVerifierThread(&verifierThread, verifyParameters); LOG_EXT(LEVEL_INFO, "Sending random token for IDT to sign..."); byte aucHostChallenge[TOKEN_SIZE]; GenerateToken(aucHostChallenge, TOKEN_SIZE); byte aucDeviceChallenge[64]; // expected device challenge length byte aucSignedDeviceChallenge[SIGNATURE_SIZE]; unsigned short usDeviceChallengeLength = sizeof(aucDeviceChallenge); unsigned short usSignedDeviceChallengeLength = sizeof(aucSignedDeviceChallenge); returnValue = ChallengeHostDevice(ucCartridgeNum, aucHostChallenge, TOKEN_SIZE, aucDeviceChallenge, &usDeviceChallengeLength, aucSignedDeviceChallenge, &usSignedDeviceChallengeLength); void* status; pthread_join(verifierThread, &status); delete verifyParameters; if (!m_bVerified) { returnValue = INVALID_CERTIFICATE_SIGNATURE; LOG_EXT(LEVEL_ERROR, "Error verifying ID certificate (error code 0x" << hex << (short)returnValue << ")."); delete certificate; return returnValue; } if (returnValue != IDTLIB_SUCCESS) { LOG_EXT(LEVEL_ERROR, "Error sending random token to IDT (error code 0x" << hex << (short)returnValue << ")."); delete certificate; return returnValue; } LOG_EXT(LEVEL_INFO, "Verifying IDT signature..."); verifyParameters = CreateVerifyParameters( certificate->IDD.GetVerifier(), aucDeviceChallenge, usDeviceChallengeLength, aucSignedDeviceChallenge, usSignedDeviceChallengeLength); CreateVerifierThread(&verifierThread, verifyParameters); LOG_EXT(LEVEL_INFO, "Getting current volume..."); returnValue = GetCurrentVolume(ucCartridgeNum, uiCurrentVolume); pthread_join(verifierThread, &status); delete verifyParameters; if (!m_bVerified) { returnValue = INVALID_TOKEN_SIGNATURE; LOG_EXT(LEVEL_ERROR, "Invalid signature (error code 0x" << hex << (short)returnValue << ")."); delete certificate; return returnValue; } if (returnValue != IDTLIB_SUCCESS) { LOG_EXT(LEVEL_ERROR, "Error getting current volume (error code 0x" << hex << (short)returnValue << ")."); delete certificate; return returnValue; } m_certificates[ucCartridgeNum] = certificate; LOG_EXT(LEVEL_INFO, "Cartridge #" << (unsigned short)ucCartridgeNum << " authentication ended successfully. Current weight: " << *uiCurrentVolume << " milligrams."); return returnValue; } catch (exception& e) { LOG_EXT(LEVEL_ERROR, "Exception caught: " << e.what() << "."); return EXCEPTION_CAUGHT; } }
/// /// Authenticates cartridge. /// int MaterialMonitorSim::AuthenticateCartridge(unsigned char ucCartridgeNum, const unsigned char *aucPubKS, unsigned char *aucIdd, unsigned short *usIddLength, unsigned int *uiCurrentVolume) { UniqueLock uniqueLock(m_mtx); int returnValue = IDTLIB_SUCCESS; if (aucPubKS == NULL && m_pubKS == NULL) { returnValue = INVALID_HOST_KEY; LOG_EXT(LEVEL_ERROR, "Invalid host key (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } if (aucIdd == NULL || usIddLength == NULL || uiCurrentVolume == NULL) { returnValue = AUTHENTICATE_NULL_PARAMS; LOG_EXT(LEVEL_ERROR, "Invalid parameters (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } if (!m_bInitialized) { returnValue = HW_NOT_INITIALIZED; LOG_EXT(LEVEL_ERROR, "Hardware not initialized (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } try { int behaviorReturnValue = GetAuthenticateCartridgeBehavior(ucCartridgeNum, aucPubKS, aucIdd, usIddLength, uiCurrentVolume); LOG_EXT(LEVEL_INFO, "Cartridge #" << (unsigned short)ucCartridgeNum << " authentication started:"); LOG_EXT(LEVEL_INFO, "Switching to cartridge #"<< (unsigned short)ucCartridgeNum << "..."); if (((m_behavior != NULL) && !IsCartridgeOn(ucCartridgeNum, m_behavior->Status)) || behaviorReturnValue == FCB_SELECT_CHANNEL_FAILED) { returnValue = FCB_SELECT_CHANNEL_FAILED; LOG_EXT(LEVEL_ERROR, "Error switching to cartridge #"<< (unsigned short)ucCartridgeNum << " (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } ResetCartridgeInfo(ucCartridgeNum); // read certificate file LOG_EXT(LEVEL_INFO, "Getting ID certificate..."); string sCertificateFileName = GetCartridgeFileName(ucCartridgeNum, CERTIFICATE_FILE); FILE *pCertificateFile = fopen(sCertificateFileName.c_str(), "rb"); if (pCertificateFile == NULL || behaviorReturnValue == INVALID_CERTIFICATE_FILE) { returnValue = INVALID_CERTIFICATE_FILE; LOG_EXT(LEVEL_ERROR, "Error getting ID certificate (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } fseek(pCertificateFile , 0 , SEEK_END); size_t fileSize = (size_t)ftell(pCertificateFile); rewind(pCertificateFile); fread(aucIdd, sizeof(unsigned char), fileSize, pCertificateFile); IDCertificate idc; *usIddLength = (unsigned short)idc.Decode(aucIdd) - SIGNATURE_SIZE; ECDSA<EC2N, SHA256>::PublicKey* pubKS; if (aucPubKS != NULL) { pubKS = LoadPublicKey(aucPubKS); if (pubKS == NULL) { return INVALID_HOST_KEY; } } else { pubKS = m_pubKS; } if (returnValue == INVALID_HOST_KEY || behaviorReturnValue == INVALID_HOST_KEY) { returnValue = INVALID_HOST_KEY; LOG_EXT(LEVEL_ERROR, "Invalid host key (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } // verify signature: ECDSA<EC2N, SHA256>::Verifier verifier(*pubKS); bool ok; try { ok = verifier.VerifyMessage(aucIdd, *usIddLength, aucIdd + *usIddLength, SIGNATURE_SIZE); } catch (exception& e) { LOG_EXT(LEVEL_ERROR, "Error verifying ID certificate (error code 0x" << hex << (short)returnValue << "):" << e.what() << "."); ok = false; } if (!ok || behaviorReturnValue == INVALID_CERTIFICATE_SIGNATURE) { returnValue = INVALID_CERTIFICATE_SIGNATURE; LOG_EXT(LEVEL_ERROR, "Error verifying ID certificate (error code 0x" << hex << (short)returnValue << ")."); return returnValue; } // read counter returnValue = ReadCounter(ucCartridgeNum, uiCurrentVolume); if (returnValue != IDTLIB_SUCCESS) { if (returnValue == INVALID_VOLUME_SIGNATURE || behaviorReturnValue == INVALID_VOLUME_SIGNATURE) { LOG_EXT(LEVEL_ERROR, "Error verifying signature (error code 0x" << hex << (short)returnValue << ")."); } else { LOG_EXT(LEVEL_ERROR, "Error reading counter (error code 0x" << hex << (short)returnValue << ")."); } return returnValue; } returnValue = behaviorReturnValue; if (returnValue == IDTLIB_SUCCESS) { m_authenticated |= (1 << ucCartridgeNum); LOG_EXT(LEVEL_INFO, "Cartridge #" << (unsigned short)ucCartridgeNum << " authentication ended successfully. Current volume: " << *uiCurrentVolume << "."); } else { LOG_EXT(LEVEL_ERROR, "Error authenticating cartridge (error code 0x" << hex << (short)returnValue << ")."); } return returnValue; } catch (exception& e) { LOG_EXT(LEVEL_ERROR, "Exception caught: " << e.what() << "."); return EXCEPTION_CAUGHT; } }