|
|
@@ -1631,4 +1631,218 @@ int stun_attr_add_padding_str(u08bits *buf, size_t *len, u16bits padding_len)
|
|
|
return stun_attr_add_str(buf, len, STUN_ATTRIBUTE_PADDING, avalue, padding_len);
|
|
|
}
|
|
|
|
|
|
+/* OAUTH */
|
|
|
+
|
|
|
+static void remove_spaces(char *s)
|
|
|
+{
|
|
|
+ char *sfns = s;
|
|
|
+ while(*sfns) {
|
|
|
+ if(*sfns != ' ')
|
|
|
+ break;
|
|
|
+ ++sfns;
|
|
|
+ }
|
|
|
+ if(*sfns) {
|
|
|
+ if(sfns != s) {
|
|
|
+ while(*sfns && (*sfns != ' ')) {
|
|
|
+ *s = *sfns;
|
|
|
+ ++s;
|
|
|
+ ++sfns;
|
|
|
+ };
|
|
|
+ *s = 0;
|
|
|
+ } else {
|
|
|
+ while(*s) {
|
|
|
+ if(*s == ' ') {
|
|
|
+ *s = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ ++s;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void normalize_algorithm(char *s)
|
|
|
+{
|
|
|
+ char c = *s;
|
|
|
+ while(c) {
|
|
|
+ if(c=='_') c='-';
|
|
|
+ else if((c>='a')&&(c<='z')) {
|
|
|
+ c = c - 'a' + 'A';
|
|
|
+ }
|
|
|
+ ++s;
|
|
|
+ c = *s;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static size_t calculate_enc_key_length(ENC_ALG a)
|
|
|
+{
|
|
|
+ switch(a) {
|
|
|
+ case AES_128_CBC:
|
|
|
+ return 16;
|
|
|
+ case AES_256_CBC:
|
|
|
+ return 32;
|
|
|
+ default:
|
|
|
+ ;
|
|
|
+ };
|
|
|
+
|
|
|
+ return 32;
|
|
|
+}
|
|
|
+
|
|
|
+static size_t calculate_auth_key_length(AUTH_ALG a)
|
|
|
+{
|
|
|
+ switch(a) {
|
|
|
+ case AUTH_ALG_HMAC_SHA_1:
|
|
|
+ return 20;
|
|
|
+ case AUTH_ALG_HMAC_SHA_256_128:
|
|
|
+ return 32;
|
|
|
+ case AUTH_ALG_HMAC_SHA_256:
|
|
|
+ return 32;
|
|
|
+ default:
|
|
|
+ ;
|
|
|
+ };
|
|
|
+
|
|
|
+ return 32;
|
|
|
+}
|
|
|
+
|
|
|
+static int calculate_key(char *key, size_t key_size, char *new_key, size_t new_key_size, SHATYPE shatype,
|
|
|
+ char *err_msg, size_t err_msg_size)
|
|
|
+{
|
|
|
+ //Extract:
|
|
|
+ u08bits prk[128];
|
|
|
+ unsigned int prk_len = 0;
|
|
|
+ stun_calculate_hmac((const u08bits *)key, key_size, (const u08bits *)"", 0, prk, &prk_len, shatype);
|
|
|
+
|
|
|
+ //Expand:
|
|
|
+ u08bits buf[128];
|
|
|
+ buf[0]=1;
|
|
|
+ u08bits hmac[128];
|
|
|
+ unsigned int hmac_len = 0;
|
|
|
+ stun_calculate_hmac((const u08bits *)buf, 1, prk, prk_len, hmac, &hmac_len, shatype);
|
|
|
+ ns_bcopy(hmac,new_key,hmac_len);
|
|
|
+
|
|
|
+ //Check
|
|
|
+ if(new_key_size>hmac_len) {
|
|
|
+ ns_bcopy(hmac,buf,hmac_len);
|
|
|
+ buf[hmac_len]=2;
|
|
|
+ u08bits hmac1[128];
|
|
|
+ unsigned int hmac1_len = 0;
|
|
|
+ stun_calculate_hmac((const u08bits *)buf, hmac_len+1, prk, prk_len, hmac1, &hmac1_len, shatype);
|
|
|
+ ns_bcopy(hmac1,new_key+hmac_len,hmac1_len);
|
|
|
+ if(new_key_size > (hmac_len + hmac1_len)) {
|
|
|
+ if(err_msg) {
|
|
|
+ snprintf(err_msg,err_msg_size,"Wrong HKDF procedure (key sizes): output.sz=%lu, hmac(1)=%lu, hmac(2)=%lu",(unsigned long)new_key_size,(unsigned long)hmac_len,(unsigned long)hmac1_len);
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int convert_oauth_key_data(oauth_key_data *oakd, oauth_key *key, char *err_msg, size_t err_msg_size)
|
|
|
+{
|
|
|
+ if(oakd && key) {
|
|
|
+
|
|
|
+ if(!(oakd->ikm_key_size)) {
|
|
|
+ if(!(oakd->as_rs_key_size)) {
|
|
|
+ if(err_msg) {
|
|
|
+ snprintf(err_msg,err_msg_size,"AS-RS key is not defined");
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if(!(oakd->auth_key_size)) {
|
|
|
+ if(err_msg) {
|
|
|
+ snprintf(err_msg,err_msg_size,"AUTH key is not defined");
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ remove_spaces(oakd->kid);
|
|
|
+
|
|
|
+ remove_spaces(oakd->hkdf_hash_func);
|
|
|
+ remove_spaces(oakd->as_rs_alg);
|
|
|
+ remove_spaces(oakd->auth_alg);
|
|
|
+
|
|
|
+ normalize_algorithm(oakd->hkdf_hash_func);
|
|
|
+ normalize_algorithm(oakd->as_rs_alg);
|
|
|
+ normalize_algorithm(oakd->auth_alg);
|
|
|
+
|
|
|
+ if(!(oakd->kid[0])) {
|
|
|
+ if(err_msg) {
|
|
|
+ snprintf(err_msg,err_msg_size,"KID is not defined");
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ ns_bzero(key,sizeof(oauth_key));
|
|
|
+
|
|
|
+ STRCPY(key->kid,oakd->kid);
|
|
|
+
|
|
|
+ ns_bcopy(oakd->as_rs_key,key->as_rs_key,sizeof(key->as_rs_key));
|
|
|
+ key->as_rs_key_size = oakd->as_rs_key_size;
|
|
|
+ ns_bcopy(oakd->auth_key,key->auth_key,sizeof(key->auth_key));
|
|
|
+ key->auth_key_size = oakd->auth_key_size;
|
|
|
+ ns_bcopy(oakd->ikm_key,key->ikm_key,sizeof(key->ikm_key));
|
|
|
+ key->ikm_key_size = oakd->ikm_key_size;
|
|
|
+
|
|
|
+ key->timestamp = oakd->timestamp;
|
|
|
+ key->lifetime = oakd->lifetime;
|
|
|
+
|
|
|
+ key->hkdf_hash_func = SHATYPE_SHA256;
|
|
|
+ if(!strcmp(oakd->hkdf_hash_func,"SHA1") || !strcmp(oakd->hkdf_hash_func,"SHA-1")) {
|
|
|
+ key->hkdf_hash_func = SHATYPE_SHA1;
|
|
|
+ } else if(!strcmp(oakd->hkdf_hash_func,"SHA256") || !strcmp(oakd->hkdf_hash_func,"SHA-256")) {
|
|
|
+ key->hkdf_hash_func = SHATYPE_SHA256;
|
|
|
+ } else if(oakd->hkdf_hash_func[0]) {
|
|
|
+ if(err_msg) {
|
|
|
+ snprintf(err_msg,err_msg_size,"Wrong HKDF hash function algorithm: %s",oakd->hkdf_hash_func);
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ key->as_rs_alg = ENC_ALG_DEFAULT;
|
|
|
+ if(!strcmp(oakd->as_rs_alg,"AES-128-CBC")) {
|
|
|
+ key->as_rs_alg = AES_128_CBC;
|
|
|
+ } else if(!strcmp(oakd->as_rs_alg,"AES-256-CBC")) {
|
|
|
+ key->as_rs_alg = AES_256_CBC;
|
|
|
+ } else if(oakd->as_rs_alg[0]) {
|
|
|
+ if(err_msg) {
|
|
|
+ snprintf(err_msg,err_msg_size,"Wrong oAuth token encryption algorithm: %s",oakd->as_rs_alg);
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ key->auth_alg = AUTH_ALG_DEFAULT;
|
|
|
+ if(!strcmp(oakd->auth_alg,"HMAC-SHA-1") || !strcmp(oakd->auth_alg,"HMAC-SHA1")) {
|
|
|
+ key->auth_alg = AUTH_ALG_HMAC_SHA_1;
|
|
|
+ } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256")) {
|
|
|
+ key->auth_alg = AUTH_ALG_HMAC_SHA_256;
|
|
|
+ } else if(!strcmp(oakd->auth_alg,"HMAC-SHA-256-128")) {
|
|
|
+ key->auth_alg = AUTH_ALG_HMAC_SHA_256_128;
|
|
|
+ } else if(oakd->auth_alg[0]) {
|
|
|
+ if(err_msg) {
|
|
|
+ snprintf(err_msg,err_msg_size,"Wrong oAuth token hash algorithm: %s",oakd->auth_alg);
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!(key->auth_key_size)) {
|
|
|
+ key->auth_key_size = calculate_auth_key_length(key->auth_alg);
|
|
|
+ if(calculate_key(key->ikm_key,key->ikm_key_size,key->auth_key,key->auth_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!(key->as_rs_key_size)) {
|
|
|
+ key->as_rs_key_size = calculate_enc_key_length(key->as_rs_alg);
|
|
|
+ if(calculate_key(key->ikm_key,key->ikm_key_size,key->as_rs_key,key->as_rs_key_size,key->hkdf_hash_func,err_msg,err_msg_size)<0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
///////////////////////////////////////////////////////////////
|