BioAPI_RETURN BioAPI mdsutil_GetRecordByUuidAndDeviceId(CSSM_DL_DB_HANDLE hDLDB, char* UuidStr, uint32 DeviceId, CSSM_DB_RECORDTYPE RecordType, uint32 NumAttributes, CSSM_HANDLE_PTR ResultsHandle, CSSM_DB_ATTRIBUTE_DATA *OutputAttributeData) { BioAPI_RETURN retValue = CSSM_OK; CSSM_QUERY Query; CSSM_SELECTION_PREDICATE Predicate[2]; memset (&Query, 0, sizeof (CSSM_QUERY)); memset (&Predicate[0], 0, sizeof (CSSM_SELECTION_PREDICATE)); memset (&Predicate[1], 0, sizeof (CSSM_SELECTION_PREDICATE)); Query.RecordType = RecordType; Query.Conjunctive = CSSM_DB_AND; Query.NumSelectionPredicates = 2; Query.SelectionPredicate = Predicate; Query.QueryLimits.TimeLimit = CSSM_QUERY_TIMELIMIT_NONE; Query.QueryLimits.SizeLimit = CSSM_QUERY_SIZELIMIT_NONE; Query.QueryFlags = 0; Predicate[0].DbOperator = CSSM_DB_EQUAL; Predicate[0].Attribute.Info = s_BioApiAttrInfo_ModuleId; Predicate[0].Attribute.Value = (CSSM_DATA *) BioAPI_malloc(sizeof (CSSM_DATA), NULL); if (Predicate[0].Attribute.Value == NULL) return CSSM_ERRCODE_MEMORY_ERROR; Predicate[0].Attribute.NumberOfValues = 1; Predicate[0].Attribute.Value->Data = (unsigned char *)UuidStr; Predicate[0].Attribute.Value->Length = (uint32)strlen (UuidStr) + 1; Predicate[1].DbOperator = CSSM_DB_EQUAL; Predicate[1].Attribute.Info = s_BioApiAttrInfo_DeviceId; Predicate[1].Attribute.Value = (CSSM_DATA *) BioAPI_malloc(sizeof (CSSM_DATA), NULL); if (Predicate[1].Attribute.Value == NULL) { BioAPI_free(Predicate[0].Attribute.Value, NULL); return CSSM_ERRCODE_MEMORY_ERROR; } Predicate[1].Attribute.NumberOfValues = 1; Predicate[1].Attribute.Value->Data = (unsigned char *)&DeviceId; Predicate[1].Attribute.Value->Length = (uint32)sizeof(uint32); retValue = mdsutil_GetRecord(hDLDB, Query, RecordType, NumAttributes, ResultsHandle, OutputAttributeData); BioAPI_free(Predicate[0].Attribute.Value, NULL); BioAPI_free(Predicate[1].Attribute.Value, NULL); return retValue; }
BioAPI_RETURN BioAPI mdsutil_GetModulePath (CSSM_DATA ModuleName, CSSM_DATA ModuleSearchPath, CSSM_DATA_PTR ModulePath) { uint8 *SearchPtr; uint8 *ptr; uint32 len; CSSM_DATA tmpPath; struct _stat st; // Check for blank search path; just use the system search path if (ModuleSearchPath.Length == 0) { if ((ModulePath->Data = (uint8*)BioAPI_malloc (ModuleName.Length, NULL)) == NULL) return (CSSM_ERRCODE_MEMORY_ERROR); strcpy ((char*) ModulePath->Data, (char*) ModuleName.Data); ModulePath->Length = ModuleName.Length; return BioAPI_OK; } // if len = ModuleSearchPath.Length + ModuleName.Length + 2; if ((ptr = (uint8*)BioAPI_malloc (len, NULL)) == NULL) return (CSSM_ERRCODE_MEMORY_ERROR); SearchPtr = ModuleSearchPath.Data; tmpPath.Data = ModuleSearchPath.Data; tmpPath.Length = ModuleSearchPath.Length; while (SearchPtr) { SearchPtr = memchr (tmpPath.Data, PATH_SEPARATOR, tmpPath.Length); if (SearchPtr != NULL) { tmpPath.Length = (uint32)(SearchPtr - tmpPath.Data); SearchPtr++; /* Skip the PATH_SEPARATOR */ } else { /* * get rid of the null character at the end of search path, if any. */ if (tmpPath.Data[tmpPath.Length-1] == '\0') tmpPath.Length--; } ModulePath->Data = ptr; memcpy(ptr, tmpPath.Data, tmpPath.Length); ptr = ptr + tmpPath.Length; *ptr++ = DIRECTORY_SEPARATOR; memcpy(ptr, ModuleName.Data, ModuleName.Length); /* copy relative path */ ptr = ptr + ModuleName.Length; /* move to end of string */ *ptr = '\0'; /* null terminate */ ModulePath->Length = (uint32)(ptr - ModulePath->Data); /* * stat the file and find out if we have found it. * If yes, then return else continue searching the * search path. */ if ((_stat((const char *)ModulePath->Data, &st)) == 0) return (CSSM_OK); tmpPath.Data = SearchPtr; if(SearchPtr != NULL) tmpPath.Length = (uint32)(ModuleSearchPath.Length - (uint32)(SearchPtr - ModuleSearchPath.Data)); } return (CSSM_ERRCODE_MDS_ERROR); }
BioAPI_RETURN BioAPI mdsutil_DeleteRecordByUuid(CSSM_DL_DB_HANDLE hDLDB, const BioAPI_UUID *uuid, CSSM_DB_RECORDTYPE RecordType) { CSSM_QUERY Query; CSSM_SELECTION_PREDICATE Predicate; CSSM_DB_UNIQUE_RECORD_PTR RecordId = NULL; BioAPI_RETURN retValue = CSSM_OK; CSSM_HANDLE ResultsHandle = 0; char UuidStr[BioAPI_PRINTABLE_UUID_LENGTH]; memset (&Query, 0, sizeof (CSSM_QUERY)); memset (&Predicate, 0, sizeof (CSSM_SELECTION_PREDICATE)); Query.RecordType = RecordType; Query.Conjunctive = CSSM_DB_NONE; Query.NumSelectionPredicates = 1; Query.SelectionPredicate = &Predicate; Query.QueryLimits.TimeLimit = CSSM_QUERY_TIMELIMIT_NONE; Query.QueryLimits.SizeLimit = CSSM_QUERY_SIZELIMIT_NONE; Query.QueryFlags = 0; Predicate.DbOperator = CSSM_DB_EQUAL; /* * Convert the Uuid to a string. */ BioAPI_GetPrintableUUID (uuid, UuidStr); Predicate.Attribute.Info = s_BioApiAttrInfo_ModuleId; Predicate.Attribute.Value = (CSSM_DATA *) BioAPI_malloc(sizeof (CSSM_DATA), 0); if (Predicate.Attribute.Value == NULL) return (CSSM_ERRCODE_MEMORY_ERROR); Predicate.Attribute.NumberOfValues = 1; Predicate.Attribute.Value->Data = (unsigned char *)UuidStr; Predicate.Attribute.Value->Length = (uint32)strlen (UuidStr) + 1; if( !IsBadCodePtr((CSSM_PROC_ADDR)MDSFuncs.DataGetFirst)) retValue = MDSFuncs.DataGetFirst(hDLDB, /* DLDBHandle */ &Query, &ResultsHandle, NULL, NULL, &RecordId); while (CSSM_OK == retValue) { if( !IsBadCodePtr((CSSM_PROC_ADDR)MDSFuncs.DataDelete)) retValue = MDSFuncs.DataDelete(hDLDB, RecordId); if( !IsBadCodePtr((CSSM_PROC_ADDR)MDSFuncs.FreeUniqueRecord)) MDSFuncs.FreeUniqueRecord(hDLDB, RecordId); if( !IsBadCodePtr((CSSM_PROC_ADDR)MDSFuncs.DataGetNext)) retValue = MDSFuncs.DataGetNext(hDLDB, /* DLDBHandle */ ResultsHandle, NULL, NULL, &RecordId); } if (CSSMERR_DL_ENDOFDATA == retValue) { retValue = CSSM_OK; } MDSFuncs.DataAbortQuery( hDLDB, ResultsHandle ); BioAPI_free(Predicate.Attribute.Value, NULL); return (retValue); }
BioAPI_RETURN _biospi_Process( ADDIN_ATTACH_DATA *pAttachData, const void *pLoadData, const BioAPI_BIR *pBIRtoProcess, BioAPI_BIR_HANDLE_PTR ProcessedBIR ) { BIR_LIST_NODE *pOldList = NULL, *pHeadNode = NULL; BIO_DATA_HEADER bioDataHeader; uint32 newBioDataLength; uint8 *pNewBioData; /*--------------------------------* * Check for the proper BIR flags * *--------------------------------*/ /*----------------------------------------------------------------------------* * Note about signed BIRs: if this BSP could somehow support signed BIRs, the * * signature would be verified at this point. Note that this means that flag * * can be discarded below to account for the check which could occur at this * * point in the future, if signatures were implemented here. * *----------------------------------------------------------------------------*/ /* Only raw BIRs should be processed. Signed raw data is OK, * so strip that flag off before the check. This is to allow * for the possibility of signed BIRs in the future; see above. */ if (pBIRtoProcess->Header.Type & ~BioAPI_BIR_DATA_TYPE_SIGNED != BioAPI_BIR_DATA_TYPE_RAW) return (BioAPIERR_BSP_INVALID_BIR); /* Only enrollment purpose is supported. Since the Verify * function requires that the BIR captured for verification comes * to it with the password in plaintext, even the * CSSM_HRS_PURPOSE_VERIFY is not supported in this function. * When a BIR is "processed" within the context of this BSP, * it can then be used to "enroll" a BIR for a payload which is * stored in plaintext, instead of encrypted. */ if (BioAPI_PURPOSE_ENROLL_FOR_VERIFICATION_ONLY != pBIRtoProcess->Header.PurposeMask) return (BioAPIERR_BSP_PURPOSE_NOT_SUPPORTED); /* Only BIRs utilizing the proper biometric data format can be used */ if (BIO_DATA_FORMAT_ID != LocalEndian2 (pBIRtoProcess->Header.Format.FormatID) || BIO_DATA_FORMAT_OWNER != LocalEndian2 (pBIRtoProcess->Header.Format.FormatOwner)) return (BioAPIERR_BSP_UNSUPPORTED_FORMAT); /*----------------------* * Create processed BIR * *----------------------*/ /* copy the biometric header */ port_memcpy((void*)&bioDataHeader, (void*)pBIRtoProcess->BiometricData, sizeof(BIO_DATA_HEADER)); /* calc length of biometric data */ newBioDataLength = bioDataHeader.PWLength + bioDataHeader.PayloadLength + sizeof(BIO_DATA_HEADER); /* allocate memory for the "biometric" data */ pNewBioData = BioAPI_malloc(newBioDataLength, NULL); if (NULL == pNewBioData) return (BioAPIERR_BSP_MEMORY_ERROR); /* In this biometric format, the header describing the length * of the password and payload, the cryptographic salts, and the * cryptographic initialization data vector is included in the * opaque biometric data first, followed by the password, then * the payload. We copy the headers and PW data over first */ port_memcpy((void*)pNewBioData, (void*)&bioDataHeader, sizeof(BIO_DATA_HEADER)); port_memcpy((void*)(pNewBioData + sizeof(BIO_DATA_HEADER)), (void*)(pBIRtoProcess->BiometricData + sizeof(BIO_DATA_HEADER)), bioDataHeader.PWLength); /* Then we copy over the payload */ port_memcpy((void*)(pNewBioData + sizeof(BIO_DATA_HEADER) + bioDataHeader.PWLength), (void*)(pBIRtoProcess->BiometricData + sizeof(BIO_DATA_HEADER) + bioDataHeader.PWLength), bioDataHeader.PayloadLength); /* Keep track of BIR in addin until function FreeBIRHandle(...) * releases it */ pOldList = pAttachData->BIRList; pAttachData->BIRList = pHeadNode = (BIR_LIST_NODE*) BioAPI_malloc(sizeof(BIR_LIST_NODE), NULL); if (NULL == pHeadNode) { BioAPI_free (pNewBioData, NULL); return (BioAPIERR_BSP_MEMORY_ERROR); } pHeadNode->NextNode = (void*)pOldList; /* Build BIR Header */ pHeadNode->BIRHandle = *ProcessedBIR = pAttachData->HandleIndex++; pHeadNode->BIR.Header.HeaderVersion = BIR_HEADER_VERSION; pHeadNode->BIR.Header.Type = BioAPI_BIR_DATA_TYPE_PROCESSED; pHeadNode->BIR.Header.Format.FormatOwner = LittleEndian2 (BIO_DATA_FORMAT_OWNER); pHeadNode->BIR.Header.Format.FormatID = LittleEndian2 (BIO_DATA_FORMAT_ID); pHeadNode->BIR.Header.Quality = 100; /* by definition */ pHeadNode->BIR.Header.FactorsMask = LittleEndian4 (BioAPI_FACTOR_PASSWORD); /* The input BIR's header has the length already converted to little-endian */ pHeadNode->BIR.Header.Length = pBIRtoProcess->Header.Length; /* This BIR is just another incarnation of the input BIR - * it has the same purpose */ pHeadNode->BIR.Header.PurposeMask = pBIRtoProcess->Header.PurposeMask; /* Finish BIR */ pHeadNode->BIR.Signature = NULL; pHeadNode->BIR.BiometricData = (BioAPI_BIR_BIOMETRIC_DATA*)pNewBioData; return BioAPI_OK; }
BioAPI_RETURN _biospi_CreateTemplate( ADDIN_ATTACH_DATA *pAttachData, const void *pLoadData, const BioAPI_BIR *pBIRtoWrap, BioAPI_BIR_HANDLE_PTR NewTemplate, const BioAPI_DATA *Payload ) { BIR_LIST_NODE *pOldList = NULL, *pHeadNode = NULL; uint8 *pNewBioData = NULL; uint32 newBioDataLength = 0; BIO_DATA_HEADER bioDataHeader; /*---------------------------------------------------------* * Only BIRs with the purpose of enrollment should be used * *---------------------------------------------------------*/ if (BioAPI_PURPOSE_ENROLL_FOR_VERIFICATION_ONLY != pBIRtoWrap->Header.PurposeMask) return (BioAPIERR_BSP_INVALID_BIR); /*----------------------------------------------------------------------* * Only BIRs created using the proper biometric data format can be used * *----------------------------------------------------------------------*/ if (BIO_DATA_FORMAT_ID != LocalEndian2 (pBIRtoWrap->Header.Format.FormatID) || BIO_DATA_FORMAT_OWNER != LocalEndian2 (pBIRtoWrap->Header.Format.FormatOwner)) return (BioAPIERR_BSP_UNSUPPORTED_FORMAT); /*------------------------------------------------* * Only raw and processed BIRs should be accepted * *------------------------------------------------*/ /*---------------------------------------------------* * Rewrap with payload, but don't encrypt - we no * * longer have plaintext password for key derivation * *---------------------------------------------------*/ /* Retrieve the opaque header information from the BIR */ port_memcpy((void*)&bioDataHeader, (void*)pBIRtoWrap->BiometricData, sizeof(BIO_DATA_HEADER)); /* New biometric data will include the old data plus any payload */ if (Payload) bioDataHeader.PayloadLength = Payload->Length; else bioDataHeader.PayloadLength = 0; newBioDataLength = bioDataHeader.PWLength + bioDataHeader.PayloadLength + sizeof(BIO_DATA_HEADER); pNewBioData = BioAPI_malloc(newBioDataLength, NULL); if (!pNewBioData) return (BioAPIERR_BSP_MEMORY_ERROR); /*---------------------------------------------------* * Move the payload into the addin's memory space, * * so that it can be included in a new template BIR * *---------------------------------------------------*/ /* In this biometric format, the header describing the length * of the password and payload, the cryptographic salts, and the * cryptographic initialization data vector is included in the * opaque biometric data first, followed by the password, then * the payload. We copy the headers and PW data over first */ port_memcpy((void*)pNewBioData, (void*)&bioDataHeader, sizeof(BIO_DATA_HEADER)); port_memcpy((void*)(pNewBioData + sizeof(BIO_DATA_HEADER)), (void*)(pBIRtoWrap->BiometricData + sizeof(BIO_DATA_HEADER)), bioDataHeader.PWLength); /* Then we copy over the payload */ if (Payload) { port_memcpy((void*)(pNewBioData + sizeof(BIO_DATA_HEADER) + bioDataHeader.PWLength), (void*)Payload->Data, Payload->Length); } // if /*----------------------------------------------------* * Build template with new biometric data and payload * *----------------------------------------------------*/ /* The assumption, at this point, is that for either case of BIR * input, raw or processed, that pNewBioData contains the opaque * data field to be stored, that newBioDataLength is the length * of that field. */ /* Keep track of BIR in addin until function FreeBIRHandle(...) releases it */ pOldList = pAttachData->BIRList; pAttachData->BIRList = pHeadNode = (BIR_LIST_NODE*) BioAPI_malloc(sizeof(BIR_LIST_NODE), NULL); pHeadNode->NextNode = (void*)pOldList; /* Build BIR Header */ pHeadNode->BIRHandle = *NewTemplate = pAttachData->HandleIndex++; pHeadNode->BIR.Header.HeaderVersion = BIR_HEADER_VERSION; pHeadNode->BIR.Header.Type = BioAPI_BIR_DATA_TYPE_PROCESSED; pHeadNode->BIR.Header.Format.FormatOwner = LittleEndian2 (BIO_DATA_FORMAT_OWNER); pHeadNode->BIR.Header.Format.FormatID = LittleEndian2 (BIO_DATA_FORMAT_ID); pHeadNode->BIR.Header.Quality = 100; /* by definition */ pHeadNode->BIR.Header.FactorsMask = LittleEndian4 (BioAPI_FACTOR_PASSWORD); pHeadNode->BIR.Header.PurposeMask = BioAPI_PURPOSE_VERIFY; /* bio data length includes the format header, the password, and the payload, * while the BIR header length includes all this and the BioAPI BIR header's length */ pHeadNode->BIR.Header.Length = LittleEndian4 (newBioDataLength + sizeof(BioAPI_BIR_HEADER)); /* Finish the BIR */ pHeadNode->BIR.Signature = NULL; pHeadNode->BIR.BiometricData = (BioAPI_BIR_BIOMETRIC_DATA*)pNewBioData; return BioAPI_OK; }
BioAPI_RETURN _biospi_Capture( ADDIN_ATTACH_DATA *pAttachData, BioAPI_BIR_PURPOSE Purpose, BioAPI_BIR_HANDLE_PTR CapturedBIR) { BIR_LIST_NODE *pOldList = NULL, *pHeadNode = NULL; uint32 capturedBIRLength = 0; BIO_DATA_HEADER bioDataHeader; #ifdef WIN32 INT_PTR dialogRetVal = 0; HANDLE dllHandle; #endif /*---------------------------------------* * Get the password from the user. * * Start of platform specific code here! * *---------------------------------------*/ /*------------------------------------------------------------------------ * WIN32 *-----------------------------------------------------------------------*/ #ifdef WIN32 /*---------------------------------------* * Create Dialog and prompt for password * *---------------------------------------*/ /* Windows will find this library in the system directory * where the .dll is installed */ dllHandle = LoadLibrary(BSP_SELF_CHECK_SECTION); if (IDOK != (dialogRetVal = DialogBox( dllHandle, MAKEINTRESOURCE(IDD_PWDIALOG), NULL, (DLGPROC)CapturePassword))) { /* Operation failed; password wasn't captured */ return (BioAPIERR_BSP_UNABLE_TO_CAPTURE); } #endif // WIN32 defined /*------------------------------------------------------------------------*/ /*---------------------------------------* * End of platform specific code. Assume * * now that the password is stored in * * the global buffer inputPassword. * *---------------------------------------*/ /* Keep track of BIR in addin until function FreeBIRHandle(...) * releases it */ pOldList = pAttachData->BIRList; pAttachData->BIRList = pHeadNode = (BIR_LIST_NODE*) BioAPI_malloc(sizeof(BIR_LIST_NODE), NULL); pHeadNode->NextNode = (void*)pOldList; /*------------------* * Build BIR Header * *------------------*/ pHeadNode->BIRHandle = *CapturedBIR = pAttachData->HandleIndex++; pHeadNode->BIR.Header.HeaderVersion = BIR_HEADER_VERSION; pHeadNode->BIR.Header.Type = BioAPI_BIR_DATA_TYPE_RAW; pHeadNode->BIR.Header.Format.FormatOwner = LittleEndian2 (BIO_DATA_FORMAT_OWNER); pHeadNode->BIR.Header.Format.FormatID = LittleEndian2 (BIO_DATA_FORMAT_ID); pHeadNode->BIR.Header.Quality = 100; /* by definition */ pHeadNode->BIR.Header.FactorsMask = LittleEndian4 (BioAPI_FACTOR_PASSWORD); /* The Purpose will be used in the HRS Process function * to make sure that BIRs which are captured for verification * are not hashed; otherwise, they're useless. */ pHeadNode->BIR.Header.PurposeMask = Purpose; bioDataHeader.PWLength = capturedBIRLength = strlen(inputPassword); bioDataHeader.PayloadLength = 0; pHeadNode->BIR.Header.Length = LittleEndian4 (sizeof(BioAPI_BIR_HEADER) + sizeof(BIO_DATA_HEADER) + capturedBIRLength); /* Finish BIR */ pHeadNode->BIR.Signature = NULL; pHeadNode->BIR.BiometricData = (BioAPI_BIR_BIOMETRIC_DATA*) BioAPI_malloc(capturedBIRLength + sizeof(BIO_DATA_HEADER), NULL); port_memcpy((void*)pHeadNode->BIR.BiometricData, (void*)&bioDataHeader, sizeof(BIO_DATA_HEADER)); port_memcpy((void*)(pHeadNode->BIR.BiometricData + sizeof(BIO_DATA_HEADER)), inputPassword, capturedBIRLength); /* Wipe password out of buffer */ port_memset((void*)inputPassword, 0, MAX_PASSWORD_SIZE); return BioAPI_OK; }