diff options
Diffstat (limited to 'src/location-appman-crypt.c')
-rw-r--r-- | src/location-appman-crypt.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/src/location-appman-crypt.c b/src/location-appman-crypt.c new file mode 100644 index 0000000..5541f73 --- /dev/null +++ b/src/location-appman-crypt.c @@ -0,0 +1,188 @@ +/* + * liblocation-appman + * + * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com> + * Genie Kim <daejins.kim@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <glib.h> +#include <gcrypt.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include "location-appman.h" +#include "location-appman-log.h" +#include "location-appman-crypt.h" + +#define CIPHER_ALGORITHM GCRY_CIPHER_BLOWFISH +#define CIPHER_MODE GCRY_CIPHER_MODE_ECB +#define ONE_CIPHER_ALGORITHM_MIN_KEY_LENGTH 5 +#define ONE_CIPHER_ALGORITHM_MAX_KEY_LENGTH 32 + +static const char *key_string = "LocationAppman"; + +static void *string2hex(const char *string, size_t *buff_len) +{ + LOCATION_APPMAN_NULL_ARG_CHECK(string); + LOCATION_APPMAN_NULL_ARG_CHECK(buff_len); + + *buff_len = g_utf8_strlen(string, -1)*2+1; + unsigned char *buffer = g_malloc0_n (*buff_len, sizeof(unsigned char*)); + unsigned int idx = 0; + for (idx = 0; idx < *buff_len; idx+=2) { + char temp[3]; + if (!g_ascii_isalnum(string[idx/2])) { + break; + } + g_snprintf (temp, 3, "%x", (unsigned int)string[idx/2]); + buffer[idx] = temp[0]; + buffer[idx+1] = temp[1]; + } + buffer[*buff_len-1] = '\0'; + return buffer; +} + +static gboolean +location_appman_encrypt_decrypt(gboolean is_encrypt, const void *key_buf, size_t key_buflen, void *inbuf, void *outbuf) +{ + LOCATION_APPMAN_NULL_ARG_CHECK(inbuf); + LOCATION_APPMAN_NULL_ARG_CHECK(outbuf); + + gpg_error_t err; + gcry_cipher_hd_t hd; + int keylen, len; + void *outblock = NULL; + void *inblock = NULL; + + len = strlen((char *)inbuf); + + err = gcry_cipher_open(&hd, CIPHER_ALGORITHM, CIPHER_MODE, 0); + if(err) { + LOCATION_APPMAN_LOG("fail to gcry_cipher_open: %s\n", gpg_strerror (err)); + return FALSE; + } + + keylen = gcry_cipher_get_algo_keylen(CIPHER_ALGORITHM); + if(!keylen) { + LOCATION_APPMAN_LOG("fail to gcry_cipher_get_algo_keylen, %d\n", keylen); + return FALSE; + } + + if(keylen < ONE_CIPHER_ALGORITHM_MIN_KEY_LENGTH || keylen > ONE_CIPHER_ALGORITHM_MAX_KEY_LENGTH) + { + LOCATION_APPMAN_LOG("keylength problem (%d)", keylen); + return FALSE; + } + + err = gcry_cipher_setkey(hd, key_buf, key_buflen); + if(err) { + //delete + LOCATION_APPMAN_LOG("fail to gcry_cipher_setkey: %s\n", gpg_strerror (err)); + gcry_cipher_close(hd); + return FALSE; + } + + inblock = gcry_xmalloc (keylen); + outblock = gcry_xmalloc (keylen); + int idx =0 ; + while(idx < len) { + size_t tlen = ((len - idx)<keylen)? len-idx : keylen; + memset(inblock, 0, keylen); + memset(outblock, 0, keylen); + if(!memcpy(inblock, inbuf+idx, tlen)) { + LOCATION_APPMAN_LOG("location_appman_encrypt_decrypt : inblock MEMCPY ERROR/n"); + break; + } + + if(is_encrypt) err = gcry_cipher_encrypt(hd, outblock, keylen, inblock, keylen); + else err = gcry_cipher_decrypt(hd, outblock, keylen, inblock, keylen); + + if(err) { + LOCATION_APPMAN_LOG("fail to gcry_cipher_encrypt/gcry_cipher_decrypt : %s\n", gpg_strerror (err)); + break; + } + if(!memcpy(outbuf+idx, outblock, keylen)) { + LOCATION_APPMAN_LOG("gcry_cipher_decrypt : outbuf MEMCPY ERROR/n"); + } + break; + } + idx += keylen; + gcry_free(inblock); + gcry_free(outblock); + return TRUE; +} + +int location_appman_encrypt(const char *key, const char *input, char *output) +{ + LOCATION_APPMAN_NULL_ARG_CHECK(input); + void *keybuf = NULL; + char tmp_outbuf[ONE_CIPHER_ALGORITHM_MAX_KEY_LENGTH] = {0, }; + size_t key_buflen; + + if(key == NULL) + keybuf = string2hex(key_string, &key_buflen); + else + keybuf = string2hex(key, &key_buflen); + + if(NULL != keybuf) { + if(!location_appman_encrypt_decrypt(TRUE, keybuf, key_buflen, (void *)input, (void *)tmp_outbuf)) { + LOCATION_APPMAN_LOG("location_appman_encrypt : location_private_encrypt_decrypt FAIL!!!\n"); + + return LOCATION_APPMAN_CRYPT_ERROR_GCRYPT; + }else { + strcpy(output, tmp_outbuf); + } + }else { + LOCATION_APPMAN_LOG("location_appman_encrypt : keybuf is NULL\n"); + return LOCATION_APPMAN_CRYPT_ERROR_INTERNAL; + } + + if(keybuf) gcry_free (keybuf); + + return LOCATION_APPMAN_CRYPT_ERROR_NONE; +} + + +int location_appman_decrypt(const char *key, const char *input, char *output) +{ + LOCATION_APPMAN_NULL_ARG_CHECK(input); + size_t key_buflen; + void *keybuf = NULL; + char tmp_outbuf[ONE_CIPHER_ALGORITHM_MAX_KEY_LENGTH] = {0, }; + + if(key == NULL) + keybuf = string2hex(key_string, &key_buflen); + else + keybuf = string2hex(key, &key_buflen); + + if(NULL != keybuf) { + if(!location_appman_encrypt_decrypt(FALSE, keybuf, key_buflen, (void *)input, (void *)tmp_outbuf)) { + LOCATION_APPMAN_LOG("location_appman_decrypt : location_private_encrypt_decrypt FAIL!!\n");; + return LOCATION_APPMAN_CRYPT_ERROR_GCRYPT; + }else { + strcpy(output, tmp_outbuf); + } + }else { + LOCATION_APPMAN_LOG("location_appman_decrypt : keybuf is NULL\n"); + return LOCATION_APPMAN_CRYPT_ERROR_INTERNAL; + } + + if (keybuf) gcry_free (keybuf); + + return LOCATION_APPMAN_CRYPT_ERROR_NONE; +} |