/*- * Copyright (c) 2006 Fredrik Lindberg. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: bioapi.c 57 2006-02-23 14:15:13Z fli $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Attach a BSP to the BioAPI framework * Arguments * bsp_uuid - BioAPI UUID string identifying the BSP * * Returns a BioAPI handle which can be used to reference this * BSP for further operations. */ BioAPI_HANDLE * bioapi_attach_bsp(const char *bsp_uuid) { BioAPI_RETURN bioReturn; BioAPI_VERSION Version; const BioAPI_UUID uuid; BioAPI_HANDLE *handle = malloc(sizeof(BioAPI_HANDLE));; bioReturn = BioAPI_GetStructuredUUID(bsp_uuid, (BioAPI_UUID *)&uuid); bioReturn = BioAPI_ModuleLoad(&uuid, 0, NULL, 0); if (bioReturn != BioAPI_OK) return (NULL); Version.Major = BioAPI_MAJOR; Version.Minor = BioAPI_MINOR; bioReturn = BioAPI_ModuleAttach(&uuid, &Version, &BioAPIMemoryFuncs, 0, 0,0,0, NULL, 0, NULL, handle); if (bioReturn != BioAPI_OK) return (NULL); return (handle); } /* * Detach a BSP from the BioAPI framework * Arguments * handle - BioAPI handle returned from bioapi_attach_bsp() * bsp_uuid - BioAPI UUID string identifying the BSP */ void bioapi_detach_bsp(BioAPI_HANDLE *handle, const char *bsp_uuid) { const BioAPI_UUID uuid; BioAPI_GetStructuredUUID(bsp_uuid, (BioAPI_UUID *)&uuid); BioAPI_ModuleUnload(&uuid, NULL, 0); BioAPI_ModuleDetach(*handle); free(handle); } /* * Initialize the BioAPI framework */ int bioapi_init() { BioAPI_RETURN bioReturn; BioAPI_VERSION bioVersion; bioVersion.Major = BioAPI_MAJOR; bioVersion.Minor = BioAPI_MINOR; bioReturn = BioAPI_Init(&bioVersion, 0, NULL, 0, NULL); if (bioReturn != BioAPI_OK) { if (bioReturn == BioAPIERR_H_FRAMEWORK_INCOMPATIBLE_VERSION) fprintf(stderr, "BioAPI ABI version missmatch\n"); return (-1); } return (0); } /* * Close the BioAPI framework */ void bioapi_destroy() { BioAPI_Terminate(); } /* * Returns a human-readable list of avaiable BSPs * Arguments * bsp_list - address of a pointer to a struct bsp_list * * Returns the number of elements in the list and bsp_list will * be populated accordingly. * Returns < 0 on failure. */ int bioapi_get_bsp_list(struct bsp_list **bsp_list) { BioAPI_RETURN bio_retval; BioAPI_BSP_SCHEMA *bsp_schemas, *cur_bsp; int elmts, elmts_r, i; struct bsp_list *bsps; bio_retval = BioAPI_EnumModules(NULL, 0, &elmts, &elmts_r); if (bio_retval != BioAPI_OK) return (-1); cur_bsp = bsp_schemas = malloc(elmts * sizeof(BioAPI_BSP_SCHEMA)); if (bsp_schemas == NULL) return (-1); bio_retval = BioAPI_EnumModules(bsp_schemas, elmts, &elmts, &elmts_r); if (bio_retval != BioAPI_OK) { free(bsp_schemas); return (-1); } bsps = malloc(sizeof(struct bsp_list) * elmts_r); if (bsps == NULL) { free(bsp_schemas); return (-1); } for (i = 0; i < elmts_r; i++) { bsps[i].bsp_index = i; bsps[i].bsp_uuid = malloc(BioAPI_PRINTABLE_UUID_LENGTH + 1); BioAPI_GetPrintableUUID((const BioAPI_UUID *)cur_bsp->ModuleId, bsps[i].bsp_uuid); bsps[i].bsp_name = strdup(cur_bsp->BSPName); bsps[i].bsp_desc = strdup(cur_bsp->Description); bsps[i].bsp_vend = strdup(cur_bsp->Vendor); cur_bsp++; } free(bsp_schemas); *bsp_list = bsps; return (elmts_r); } /* * Free all resources allocated by bioapi_get_bsp_list * Arguments * bsp_list - Pointer to a bsp_list previously returned by get_bsp_list * len - Size of list as returned by get_bsp_list */ void bioapi_destroy_bsp_list(struct bsp_list *bsp_list, size_t len) { int i; for (i = 0; i < len; i++) { free(bsp_list[i].bsp_uuid); free(bsp_list[i].bsp_name); free(bsp_list[i].bsp_desc); free(bsp_list[i].bsp_vend); } free(bsp_list); } /* * Enroll a new user * Arguments * handle - BioAPI BSP handle of the BSP we want to talk to * bm - BIR DB backend module * bmh - BIR DB backend module handle * user - zero-terminated string with the username */ struct birdb_rec * bioapi_enroll(BioAPI_HANDLE *handle, struct birdb_mod *bm, void *bmh, const char *user) { BioAPI_RETURN bioReturn; BioAPI_BIR_HANDLE captured_template; BioAPI_BIR_PTR bir_data = NULL; struct birdb_rec *rec; int error; rec = malloc(sizeof(struct birdb_rec)); if (rec == NULL) return (NULL); bioReturn = BioAPI_Enroll(*handle, BioAPI_PURPOSE_ENROLL_FOR_VERIFICATION_ONLY, NULL, &captured_template, NULL, -1, NULL); bioReturn = BioAPI_GetBIRFromHandle(*handle, captured_template, &bir_data); if (bioReturn != BioAPI_OK) return (NULL); /* Set up our record */ rec->br_key = strdup(user); rec->br_bir = bir_data; /* Call the backend module to do the job */ error = birdb_backend_ins(bm, bmh, rec); if (error != 0) { birdb_freerec(rec); rec = NULL; } return (rec); } /* * Free resources allocated to a BIR */ void bioapi_freebir(BioAPI_BIR *bir) { free(bir->BiometricData); if (bir->Signature) { free(bir->Signature->Data); free(bir->Signature); } free(bir); } /* * Verify an existing record * Arguments * handle - BioAPI BSP handle of the BSP we want to talk to * rec - BIR db record to verify * * Returns 0 on success, 1 on failed verification, -1 on failure */ int bioapi_verify(BioAPI_HANDLE *handle, struct birdb_rec *rec) { BioAPI_BIR_HANDLE template, bir_processed; BioAPI_INPUT_BIR input_bir, bir_capture, bir_input_proc; BioAPI_BIR_HEADER bir_header; BioAPI_BOOL resp = 0, prec = BioAPI_TRUE; BioAPI_FAR far_max, far_ach; BioAPI_RETURN bioReturn; int retn = -1; bioReturn = BioAPI_Capture(*handle, BioAPI_PURPOSE_VERIFY, &template, -1, NULL); if (bioReturn != BioAPI_OK) { retn = -1; goto out; } bioReturn = BioAPI_GetHeaderFromHandle(*handle, template, &bir_header); if (bioReturn != BioAPI_OK) { retn = -1; goto out; } if (bir_header.Type == BioAPI_BIR_DATA_TYPE_INTERMEDIATE) { bir_capture.Form = BioAPI_BIR_HANDLE_INPUT; bir_capture.InputBIR.BIRinBSP = &template; bioReturn = BioAPI_Process(*handle, &bir_capture, &bir_processed); if (bioReturn != BioAPI_OK) { retn = -1; goto out; } bir_input_proc.Form = BioAPI_BIR_HANDLE_INPUT; bir_input_proc.InputBIR.BIRinBSP = &bir_processed; } else { bir_input_proc.Form = BioAPI_BIR_HANDLE_INPUT; bir_input_proc.InputBIR.BIRinBSP = &template; } input_bir.InputBIR.BIR = rec->br_bir; input_bir.Form = BioAPI_FULLBIR_INPUT; far_max = 1; bioReturn = BioAPI_VerifyMatch(*handle, &far_max, NULL, &prec, &bir_input_proc, &input_bir, NULL, &resp, &far_ach, NULL, NULL); retn = (resp) ? 0 : 1; out: return (retn); } /* * Verify an array of records existing record * Arguments * handle - BioAPI BSP handle of the BSP we want to talk to * rec - BIR db record to verify * * Returns the offset into the array which match, < 0 on failure */ int bioapi_verify_many(BioAPI_HANDLE *handle, struct birdb_rec **recs) { BioAPI_BIR_HANDLE template, bir_processed; BioAPI_INPUT_BIR input_bir, bir_capture, bir_input_proc; BioAPI_BIR_HEADER bir_header; BioAPI_BOOL resp = 0, prec = BioAPI_TRUE; BioAPI_FAR far_max, far_ach; BioAPI_RETURN bioReturn; int i, retn = -1; bioReturn = BioAPI_Capture(*handle, BioAPI_PURPOSE_VERIFY, &template, -1, NULL); if (bioReturn != BioAPI_OK) { retn = -1; goto out; } bioReturn = BioAPI_GetHeaderFromHandle(*handle, template, &bir_header); if (bioReturn != BioAPI_OK) { retn = -1; goto out; } if (bir_header.Type == BioAPI_BIR_DATA_TYPE_INTERMEDIATE) { bir_capture.Form = BioAPI_BIR_HANDLE_INPUT; bir_capture.InputBIR.BIRinBSP = &template; bioReturn = BioAPI_Process(*handle, &bir_capture, &bir_processed); if (bioReturn != BioAPI_OK) { retn = -1; goto out; } bir_input_proc.Form = BioAPI_BIR_HANDLE_INPUT; bir_input_proc.InputBIR.BIRinBSP = &bir_processed; } else { bir_input_proc.Form = BioAPI_BIR_HANDLE_INPUT; bir_input_proc.InputBIR.BIRinBSP = &template; } for (i = 0; recs[i] != NULL; i++) { input_bir.InputBIR.BIR = recs[i]->br_bir; input_bir.Form = BioAPI_FULLBIR_INPUT; far_max = 1; bioReturn = BioAPI_VerifyMatch(*handle, &far_max, NULL, &prec, &bir_input_proc, &input_bir, NULL, &resp, &far_ach, NULL, NULL); if (resp == 1) { retn = i; break; } } out: return (retn); } /* * Identify a user based on biometric data * Arguments * handle - BioAPI BSP handle of the BSP we want to talk to * username - Will be set to the matching user if any, it's the * responsibility of the called to free this memory. * * Returns 0 on success, non-zero on failure. */ int bioapi_identify(BioAPI_HANDLE *handle, struct birdb_mod *bm, void *bmh, char **username) { BioAPI_BIR_HANDLE template, bir_processed; BioAPI_INPUT_BIR input_bir, bir_capture, bir_input_proc; BioAPI_BIR_HEADER bir_header; BioAPI_BOOL resp = 0; BioAPI_BOOL prec = BioAPI_TRUE; BioAPI_FAR far_max, far_ach; BioAPI_RETURN bioReturn; struct birdb_rec *rec; int retn = -1; bioReturn = BioAPI_Capture(*handle, BioAPI_PURPOSE_VERIFY, &template, -1, NULL); if (bioReturn != BioAPI_OK) { retn = -1; goto out; } bioReturn = BioAPI_GetHeaderFromHandle(*handle, template, &bir_header); if (bioReturn != BioAPI_OK) { retn = -1; goto out; } if (bir_header.Type == BioAPI_BIR_DATA_TYPE_INTERMEDIATE) { bir_capture.Form = BioAPI_BIR_HANDLE_INPUT; bir_capture.InputBIR.BIRinBSP = &template; bioReturn = BioAPI_Process(*handle, &bir_capture, &bir_processed); if (bioReturn != BioAPI_OK) { retn = -1; goto out; } bir_input_proc.Form = BioAPI_BIR_HANDLE_INPUT; bir_input_proc.InputBIR.BIRinBSP = &bir_processed; } else { bir_input_proc.Form = BioAPI_BIR_HANDLE_INPUT; bir_input_proc.InputBIR.BIRinBSP = &template; } far_max = 1; for (rec = birdb_backend_seqgetfirst(bm, bmh); rec != NULL; rec = birdb_backend_seqgetnext(bm, bmh, rec)) { input_bir.InputBIR.BIR = rec->br_bir; input_bir.Form = BioAPI_FULLBIR_INPUT; bioReturn = BioAPI_VerifyMatch(*handle, &far_max, NULL, &prec, &bir_input_proc, &input_bir, NULL, &resp, &far_ach, NULL, NULL); if (resp) { *username = strdup(rec->br_key); retn = 0; break; } } birdb_backend_seqfree(bm, bmh, rec); out: return (retn); }