/* * rpc_server.c * ------------ * Remote procedure call server-side private API implementation. * * Copyright (c) 2016, NORDUnet A/S All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - 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. * * - Neither the name of the NORDUnet nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT * HOLDER OR CONTRIBUTORS 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. */ #include "hal.h" #include "hal_internal.h" #include "xdr_internal.h" /* * RPC calls. */ #define check(op) if ((ret = (op)) != HAL_OK) return ret; #define pad(n) (((n) + 3) & ~3) static hal_error_t get_version(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { uint32_t version; hal_error_t ret; /* call the local function */ ret = hal_rpc_local_misc_dispatch.get_version(&version); if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, version)); return ret; } static hal_error_t get_random(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { uint32_t length; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &length)); /* sanity check length */ if (length == 0 || length > olimit - *optr - 4) return HAL_ERROR_RPC_PACKET_OVERFLOW; /* call the local function */ /* get the data directly into the output buffer */ check(hal_xdr_encode_int(optr, olimit, length)); ret = hal_rpc_local_misc_dispatch.get_random(*optr, (size_t)length); if (ret == HAL_OK) *optr += pad(length); else /* don't return data if error */ *optr -= 4; return ret; } static hal_error_t set_pin(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client; uint32_t user; uint8_t *pin; uint32_t pin_len; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); check(hal_xdr_decode_int(iptr, ilimit, &user)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &pin, &pin_len)); /* call the local function */ ret = hal_rpc_local_misc_dispatch.set_pin(client, user, (const char * const)pin, pin_len); return ret; } static hal_error_t login(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client; uint32_t user; uint8_t *pin; uint32_t pin_len; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); check(hal_xdr_decode_int(iptr, ilimit, &user)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &pin, &pin_len)); /* call the local function */ ret = hal_rpc_local_misc_dispatch.login(client, user, (const char * const)pin, pin_len); return ret; } static hal_error_t logout(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); /* call the local function */ ret = hal_rpc_local_misc_dispatch.logout(client); return ret; } static hal_error_t logout_all(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_error_t ret; /* call the local function */ ret = hal_rpc_local_misc_dispatch.logout_all(); return ret; } static hal_error_t is_logged_in(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client; uint32_t user; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); check(hal_xdr_decode_int(iptr, ilimit, &user)); /* call the local function */ ret = hal_rpc_local_misc_dispatch.is_logged_in(client, user); return ret; } static hal_error_t hash_get_digest_len(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { uint32_t alg; size_t length; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &alg)); /* call the local function */ ret = hal_rpc_local_hash_dispatch.get_digest_length(alg, &length); if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, length)); return ret; } static hal_error_t hash_get_digest_algorithm_id(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { uint32_t alg; size_t len; uint32_t len_max; uint8_t *optr_orig = *optr; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &alg)); check(hal_xdr_decode_int(iptr, ilimit, &len_max)); /* sanity check len_max */ if (len_max > olimit - *optr - 4) return HAL_ERROR_RPC_PACKET_OVERFLOW; /* call the local function */ /* get the data directly into the output buffer */ *optr += 4; /* reserve 4 bytes for length */ ret = hal_rpc_local_hash_dispatch.get_digest_algorithm_id(alg, *optr, &len, (size_t)len_max); if (ret == HAL_OK) { *optr = optr_orig; check(hal_xdr_encode_int(optr, olimit, len)); *optr += pad(len); } else { /* don't return data if error */ *optr = optr_orig; } return ret; } static hal_error_t hash_get_algorithm(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_hash_handle_t hash; hal_digest_algorithm_t alg; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &hash.handle)); /* call the local function */ ret = hal_rpc_local_hash_dispatch.get_algorithm(hash, &alg); if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, alg)); return ret; } static hal_error_t hash_initialize(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client; hal_session_handle_t session; hal_hash_handle_t hash; uint32_t alg; uint8_t *key; uint32_t key_len; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); check(hal_xdr_decode_int(iptr, ilimit, &alg)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &key, &key_len)); /* call the local function */ ret = hal_rpc_local_hash_dispatch.initialize(client, session, &hash, (hal_digest_algorithm_t)alg, key, (size_t)key_len); if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, hash.handle)); return ret; } static hal_error_t hash_update(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_hash_handle_t hash; uint8_t *data; uint32_t length; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &hash.handle)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &data, &length)); /* call the local function */ ret = hal_rpc_local_hash_dispatch.update(hash, data, (size_t)length); return ret; } static hal_error_t hash_finalize(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_hash_handle_t hash; uint32_t length; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &hash.handle)); check(hal_xdr_decode_int(iptr, ilimit, &length)); /* sanity check length */ if (length == 0 || length > olimit - *optr - 4) return HAL_ERROR_RPC_PACKET_OVERFLOW; /* call the local function */ /* get the data directly into the output buffer */ check(hal_xdr_encode_int(optr, olimit, length)); ret = hal_rpc_local_hash_dispatch.finalize(hash, *optr, (size_t)length); if (ret == HAL_OK) *optr += pad(length); else /* don't return data if error */ *optr -= 4; return ret; } static hal_error_t pkey_load(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client; hal_session_handle_t session; hal_pkey_handle_t pkey; uint32_t type; uint32_t curve; uint8_t *name, *der; uint32_t name_len, der_len; hal_key_flags_t flags; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); check(hal_xdr_decode_int(iptr, ilimit, &type)); check(hal_xdr_decode_int(iptr, ilimit, &curve)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &der, &der_len)); check(hal_xdr_decode_int(iptr, ilimit, &flags)); /* call the local function */ ret = hal_rpc_local_pkey_dispatch.load(client, session, &pkey, type, curve, name, name_len, der, der_len, flags); if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, pkey.handle)); return ret; } static hal_error_t pkey_find(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client; hal_session_handle_t session; hal_pkey_handle_t pkey; uint32_t type; uint8_t *name; uint32_t name_len; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); check(hal_xdr_decode_int(iptr, ilimit, &type)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); /* call the local function */ ret = hal_rpc_local_pkey_dispatch.find(client, session, &pkey, type, name, name_len); if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, pkey.handle)); return ret; } static hal_error_t pkey_generate_rsa(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client; hal_session_handle_t session; hal_pkey_handle_t pkey; uint8_t *name; uint32_t name_len; uint32_t key_len; uint8_t *exp; uint32_t exp_len; hal_key_flags_t flags; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); check(hal_xdr_decode_int(iptr, ilimit, &key_len)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &exp, &exp_len)); check(hal_xdr_decode_int(iptr, ilimit, &flags)); /* call the local function */ ret = hal_rpc_local_pkey_dispatch.generate_rsa(client, session, &pkey, name, name_len, key_len, exp, exp_len, flags); if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, pkey.handle)); return ret; } static hal_error_t pkey_generate_ec(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client; hal_session_handle_t session; hal_pkey_handle_t pkey; uint8_t *name; uint32_t name_len; uint32_t curve; hal_key_flags_t flags; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); check(hal_xdr_decode_int(iptr, ilimit, &curve)); check(hal_xdr_decode_int(iptr, ilimit, &flags)); /* call the local function */ ret = hal_rpc_local_pkey_dispatch.generate_ec(client, session, &pkey, name, name_len, curve, flags); if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, pkey.handle)); return ret; } static hal_error_t pkey_close(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_pkey_handle_t pkey; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle)); /* call the local function */ ret = hal_rpc_local_pkey_dispatch.close(pkey); return ret; } static hal_error_t pkey_delete(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_pkey_handle_t pkey; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle)); /* call the local function */ ret = hal_rpc_local_pkey_dispatch.delete(pkey); return ret; } static hal_error_t pkey_get_key_type(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_pkey_handle_t pkey; hal_key_type_t type; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle)); /* call the local function */ ret = hal_rpc_local_pkey_dispatch.get_key_type(pkey, &type); if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, type)); return ret; } static hal_error_t pkey_get_key_flags(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_pkey_handle_t pkey; hal_key_flags_t flags; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle)); /* call the local function */ ret = hal_rpc_local_pkey_dispatch.get_key_flags(pkey, &flags); if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, flags)); return ret; } static hal_error_t pkey_get_public_key_len(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_pkey_handle_t pkey; size_t len; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle)); /* call the local function */ len = hal_rpc_local_pkey_dispatch.get_public_key_len(pkey); check(hal_xdr_encode_int(optr, olimit, len)); return HAL_OK; } static hal_error_t pkey_get_public_key(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_pkey_handle_t pkey; size_t len; uint32_t len_max; uint8_t *optr_orig = *optr; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle)); check(hal_xdr_decode_int(iptr, ilimit, &len_max)); /* sanity check len_max */ if (len_max > olimit - *optr - 4) return HAL_ERROR_RPC_PACKET_OVERFLOW; /* call the local function */ /* get the data directly into the output buffer */ *optr += 4; /* reserve 4 bytes for length */ ret = hal_rpc_local_pkey_dispatch.get_public_key(pkey, *optr, &len, len_max); if (ret == HAL_OK) { *optr = optr_orig; check(hal_xdr_encode_int(optr, olimit, len)); *optr += pad(len); } else { /* don't return data if error */ *optr = optr_orig; } return ret; } static hal_error_t pkey_remote_sign(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_session_handle_t session; hal_pkey_handle_t pkey; hal_hash_handle_t hash; uint8_t *input; uint32_t input_len; uint32_t sig_max; size_t sig_len; uint8_t *optr_orig = *optr; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle)); check(hal_xdr_decode_int(iptr, ilimit, &hash.handle)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &input, &input_len)); check(hal_xdr_decode_int(iptr, ilimit, &sig_max)); /* sanity check sig_max */ if (sig_max > olimit - *optr - 4) return HAL_ERROR_RPC_PACKET_OVERFLOW; /* call the local function */ /* get the data directly into the output buffer */ *optr += 4; /* reserve 4 bytes for length */ ret = hal_rpc_local_pkey_dispatch.sign(session, pkey, hash, input, input_len, *optr, &sig_len, sig_max); *optr = optr_orig; if (ret == HAL_OK) { check(hal_xdr_encode_int(optr, olimit, sig_len)); *optr += pad(sig_len); } return ret; } static hal_error_t pkey_remote_verify(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { hal_session_handle_t session; hal_pkey_handle_t pkey; hal_hash_handle_t hash; uint8_t *input; uint32_t input_len; uint8_t *sig; uint32_t sig_len; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle)); check(hal_xdr_decode_int(iptr, ilimit, &hash.handle)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &input, &input_len)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &sig, &sig_len)); /* call the local function */ ret = hal_rpc_local_pkey_dispatch.verify(session, pkey, hash, input, input_len, sig, sig_len); return ret; } static hal_error_t hal_xdr_encode_pkey_info(uint8_t **optr, const uint8_t * const olimit, const hal_pkey_info_t *info) { uint8_t *optr_orig = *optr; hal_error_t ret; if ((ret = hal_xdr_encode_int(optr, olimit, info->type)) != HAL_OK || (ret = hal_xdr_encode_int(optr, olimit, info->curve)) != HAL_OK || (ret = hal_xdr_encode_int(optr, olimit, info->flags)) != HAL_OK || (ret = hal_xdr_encode_buffer(optr, olimit, (uint8_t *)&info->name[0], info->name_len)) != HAL_OK) *optr = optr_orig; return ret; } static hal_error_t pkey_list(uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { uint8_t *optr_orig = *optr; uint32_t result_max; hal_error_t ret; check(hal_xdr_decode_int(iptr, ilimit, &result_max)); hal_pkey_info_t result[result_max]; unsigned result_len; /* call the local function */ ret = hal_rpc_local_pkey_dispatch.list(result, &result_len, result_max); if (ret == HAL_OK) { int i; check(hal_xdr_encode_int(optr, olimit, result_len)); for (i = 0; i < result_len; ++i) { if ((ret = hal_xdr_encode_pkey_info(optr, olimit, &result[i])) != HAL_OK) { *optr = optr_orig; break; } } } return ret; } #define MAX_PKT_SIZE 4096 #define interrupt 0 static uint8_t inbuf[MAX_PKT_SIZE], outbuf[MAX_PKT_SIZE]; void hal_rpc_server_main(void) { uint8_t *iptr, *ilimit, *optr, *olimit; size_t ilen, olen; uint32_t rpc_func_num; void *opaque; hal_error_t ret; while (!interrupt) { ilen = sizeof(inbuf); ret = hal_rpc_recvfrom(inbuf, &ilen, &opaque); if (ret == HAL_OK) { iptr = inbuf; ilimit = inbuf + ilen; optr = outbuf + 4; /* reserve 4 bytes for return code */ olimit = outbuf + sizeof(outbuf); hal_xdr_decode_int(&iptr, ilimit, &rpc_func_num); switch (rpc_func_num) { case RPC_FUNC_GET_VERSION: ret = get_version(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_GET_RANDOM: ret = get_random(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_SET_PIN: ret = set_pin(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_LOGIN: ret = login(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_LOGOUT: ret = logout(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_LOGOUT_ALL: ret = logout_all(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_IS_LOGGED_IN: ret = is_logged_in(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_HASH_GET_DIGEST_LEN: ret = hash_get_digest_len(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_HASH_GET_DIGEST_ALGORITHM_ID: ret = hash_get_digest_algorithm_id(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_HASH_GET_ALGORITHM: ret = hash_get_algorithm(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_HASH_INITIALIZE: ret = hash_initialize(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_HASH_UPDATE: ret = hash_update(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_HASH_FINALIZE: ret = hash_finalize(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_LOAD: ret = pkey_load(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_FIND: ret = pkey_find(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_GENERATE_RSA: ret = pkey_generate_rsa(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_GENERATE_EC: ret = pkey_generate_ec(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_CLOSE: ret = pkey_close(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_DELETE: ret = pkey_delete(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_GET_KEY_TYPE: ret = pkey_get_key_type(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_GET_KEY_FLAGS: ret = pkey_get_key_flags(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_GET_PUBLIC_KEY_LEN: ret = pkey_get_public_key_len(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_GET_PUBLIC_KEY: ret = pkey_get_public_key(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_REMOTE_SIGN: ret = pkey_remote_sign(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_REMOTE_VERIFY: ret = pkey_remote_verify(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_LIST: ret = pkey_list(&iptr, ilimit, &optr, olimit); break; default: ret = HAL_ERROR_RPC_BAD_FUNCTION; break; } /* encode the return code at the beginning of the payload */ olen = optr - outbuf; optr = outbuf; hal_xdr_encode_int(&optr, olimit, ret); hal_rpc_sendto(outbuf, olen, opaque); } } } /* * Dispatch vectors. */ const hal_rpc_misc_dispatch_t *hal_rpc_misc_dispatch = &hal_rpc_local_misc_dispatch; const hal_rpc_hash_dispatch_t *hal_rpc_hash_dispatch = &hal_rpc_local_hash_dispatch; const hal_rpc_pkey_dispatch_t *hal_rpc_pkey_dispatch = &hal_rpc_local_pkey_dispatch; hal_error_t hal_rpc_server_init(void) { return hal_rpc_server_transport_init(); } hal_error_t hal_rpc_server_close(void) { return hal_rpc_server_transport_close(); } /* * Local variables: * indent-tabs-mode: nil * End: */ '#n199'>199 200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223





                           

                                   
  




                                                                           
  


                                                                         
  


                                                                           
  










                                                                           

   
                  
                   
                   
 
                













































































































                                                                              

                           


                            
                                         
                                                                         



                                                                          
                                                  


                         
                                                                                 
























                                                               

                                                                                 





                                                                                 
                                                    

             

                                                           
 
        





                         
   
 
               






                        
/*
 * test-pbkdf2.c
 * -------------
 * Test program for PBKDF2.
 *
 * Authors: Rob Austein
 * Copyright (c) 2015, NORDUnet A/S
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - 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.
 *
 * - Neither the name of the NORDUnet nor the names of its contributors may
 *   be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT
 * HOLDER OR CONTRIBUTORS 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.
 */

#include <stdio.h>
#include <stdint.h>
#include <string.h>

#include <hal.h>

/* PBKDF2 HMAC-SHA-1 test cases from RFC 6070. */

/* 'password' */
static const uint8_t pbkdf2_tc_1_password[] = { /* 8 bytes */
  0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64
};

/* 'salt' */
static const uint8_t pbkdf2_tc_1_salt[] = { /* 4 bytes */
  0x73, 0x61, 0x6c, 0x74
};

static const unsigned pbkdf2_tc_1_count = 1;

static const uint8_t pbkdf2_tc_1_DK[] = { /* 20 bytes */
  0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5, 0x24,
  0xaf, 0x60, 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6
};

/* 'password' */
static const uint8_t pbkdf2_tc_2_password[] = { /* 8 bytes */
  0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64
};

/* 'salt' */
static const uint8_t pbkdf2_tc_2_salt[] = { /* 4 bytes */
  0x73, 0x61, 0x6c, 0x74
};

static const unsigned pbkdf2_tc_2_count = 2;

static const uint8_t pbkdf2_tc_2_DK[] = { /* 20 bytes */
  0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 0xcd, 0x1e, 0xd9, 0x2a,
  0xce, 0x1d, 0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57
};

/* 'password' */
static const uint8_t pbkdf2_tc_3_password[] = { /* 8 bytes */
  0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64
};

/* 'salt' */
static const uint8_t pbkdf2_tc_3_salt[] = { /* 4 bytes */
  0x73, 0x61, 0x6c, 0x74
};

static const unsigned pbkdf2_tc_3_count = 4096;

static const uint8_t pbkdf2_tc_3_DK[] = { /* 20 bytes */
  0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 0xbe, 0xad, 0x49, 0xd9,
  0x26, 0xf7, 0x21, 0xd0, 0x65, 0xa4, 0x29, 0xc1
};

/* 'password' */
static const uint8_t pbkdf2_tc_4_password[] = { /* 8 bytes */
  0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64
};

/* 'salt' */
static const uint8_t pbkdf2_tc_4_salt[] = { /* 4 bytes */
  0x73, 0x61, 0x6c, 0x74
};

static const unsigned pbkdf2_tc_4_count = 16777216;

static const uint8_t pbkdf2_tc_4_DK[] = { /* 20 bytes */
  0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, 0xe9, 0x94, 0x5b, 0x3d,
  0x6b, 0xa2, 0x15, 0x8c, 0x26, 0x34, 0xe9, 0x84
};

/* 'passwordPASSWORDpassword' */
static const uint8_t pbkdf2_tc_5_password[] = { /* 24 bytes */
  0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x50, 0x41, 0x53, 0x53,
  0x57, 0x4f, 0x52, 0x44, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64
};

/* 'saltSALTsaltSALTsaltSALTsaltSALTsalt' */
static const uint8_t pbkdf2_tc_5_salt[] = { /* 36 bytes */
  0x73, 0x61, 0x6c, 0x74, 0x53, 0x41, 0x4c, 0x54, 0x73, 0x61, 0x6c, 0x74,
  0x53, 0x41, 0x4c, 0x54, 0x73, 0x61, 0x6c, 0x74, 0x53, 0x41, 0x4c, 0x54,
  0x73, 0x61, 0x6c, 0x74, 0x53, 0x41, 0x4c, 0x54, 0x73, 0x61, 0x6c, 0x74
};

static const unsigned pbkdf2_tc_5_count = 4096;

static const uint8_t pbkdf2_tc_5_DK[] = { /* 25 bytes */
  0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 0x80, 0xc8, 0xd8, 0x36,
  0x62, 0xc0, 0xe4, 0x4a, 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 0x38
};

/* 'pass\x00word' */
static const uint8_t pbkdf2_tc_6_password[] = { /* 9 bytes */
  0x70, 0x61, 0x73, 0x73, 0x00, 0x77, 0x6f, 0x72, 0x64
};

/* 'sa\x00lt' */
static const uint8_t pbkdf2_tc_6_salt[] = { /* 5 bytes */
  0x73, 0x61, 0x00, 0x6c, 0x74
};

static const unsigned pbkdf2_tc_6_count = 4096;

static const uint8_t pbkdf2_tc_6_DK[] = { /* 16 bytes */
  0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 0xcc, 0x37, 0xd7, 0xf0,
  0x34, 0x25, 0xe0, 0xc3
};

static void print_hex(const uint8_t * const val, const size_t len)
{
  size_t i;
  for (i = 0; i < len; i++)
    printf(" %02x", val[i]);
}

static int _test_pbkdf2(hal_core_t *core,
                        const uint8_t * const pwd,  const size_t pwd_len,
                        const uint8_t * const salt, const size_t salt_len,
                        const uint8_t * const dk,   const size_t dk_len,
                        const unsigned count, const char * const label)
{
  printf("Starting PBKDF2 test case %s\n", label);

  uint8_t result[dk_len];

  hal_error_t err = hal_pbkdf2(core, hal_hash_sha1, pwd, pwd_len, salt, salt_len,
                               result, dk_len, count);

  if (err != HAL_OK) {
    printf("hal_pbkdf2() failed: %s\n", hal_error_string(err));
    return 0;
  }

  printf("Comparing result with known value\n");

  if (memcmp(dk, result, dk_len)) {
    printf("MISMATCH\nExpected:");
    print_hex(dk, dk_len);
    printf("\nGot:     ");
    print_hex(result, dk_len);
    printf("\n");
    return 0;
  }

  else {
    printf("OK\n");
    return 1;
  }
}

#define test_pbkdf2(_n_) \
  _test_pbkdf2(core,                                                            \
               pbkdf2_tc_##_n_##_password, sizeof(pbkdf2_tc_##_n_##_password),  \
               pbkdf2_tc_##_n_##_salt,     sizeof(pbkdf2_tc_##_n_##_salt),      \
               pbkdf2_tc_##_n_##_DK,       sizeof(pbkdf2_tc_##_n_##_DK),        \
               pbkdf2_tc_##_n_##_count,    #_n_)

int main (int argc, char *argv[])
{
  hal_core_t *core = hal_core_find(SHA1_NAME, NULL);
  int ok = 1;

  if (core == NULL)
    printf("SHA-1 core not present, not testing PBKDF2\n");

  else {
    ok &= test_pbkdf2(1);
    ok &= test_pbkdf2(2);
    ok &= test_pbkdf2(3);
    ok &= test_pbkdf2(4);
    ok &= test_pbkdf2(5);
    ok &= test_pbkdf2(6);
  }

    return !ok;
}

/*
 * Local variables:
 * indent-tabs-mode: nil
 * End:
 */