/* Note that this skips CRs so implementations always see just straight LFs as line terminators */ static int process_dash_escaped(dearmour_arg_t *arg,ops_error_t **errors, ops_reader_info_t *rinfo, ops_parse_cb_info_t *cbinfo) { ops_parser_content_t content; ops_parser_content_t content2; ops_signed_cleartext_body_t *body=&content.content.signed_cleartext_body; ops_signed_cleartext_trailer_t *trailer =&content2.content.signed_cleartext_trailer; const char *hashstr; ops_hash_t *hash; int total; hash=malloc(sizeof *hash); hashstr=ops_find_header(&arg->headers,"Hash"); if(hashstr) { ops_hash_algorithm_t alg; alg=ops_hash_algorithm_from_text(hashstr); if(!ops_is_hash_alg_supported(&alg)) { free(hash); OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unsupported hash algorithm '%s'",hashstr); return -1; } if(alg == OPS_HASH_UNKNOWN) { free(hash); OPS_ERROR_1(errors,OPS_E_R_BAD_FORMAT,"Unknown hash algorithm '%s'",hashstr); return -1; } ops_hash_any(hash,alg); } else ops_hash_md5(hash); hash->init(hash); body->length=0; total=0; for( ; ; ) { int c; unsigned count; if((c=read_char(arg,errors,rinfo,cbinfo,ops_true)) < 0) return -1; if(arg->prev_nl && c == '-') { if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) return -1; if(c != ' ') { /* then this had better be a trailer! */ if(c != '-') OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad dash-escaping"); for(count=2 ; count < 5 ; ++count) { if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) return -1; if(c != '-') OPS_ERROR(errors,OPS_E_R_BAD_FORMAT,"Bad dash-escaping (2)"); } arg->state=AT_TRAILER_NAME; break; } /* otherwise we read the next character */ if((c=read_char(arg,errors,rinfo,cbinfo,ops_false)) < 0) return -1; } if(c == '\n' && body->length) { if(!(memchr(body->data+1,'\n',body->length-1) == NULL)) // ASSERT(memchr(body->data+1,'\n',body->length-1) == NULL); { fprintf(stderr,"no \\n in armoured file.") ; return -1 ; } if(body->data[0] == '\n') hash->add(hash,(unsigned char *)"\r",1); hash->add(hash,body->data,body->length); if (debug) { fprintf(stderr,"Got body:\n%s\n",body->data); } CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content); body->length=0; } body->data[body->length++]=c; ++total; if(body->length == sizeof body->data) { if (debug) { fprintf(stderr,"Got body (2):\n%s\n",body->data); } CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY,&content); body->length=0; } } if(!(body->data[0] == '\n')) // ASSERT(body->data[0] == '\n'); { fprintf(stderr,"Body should end with \\n\n"); return -1 ; } if(!(body->length == 1)) // ASSERT(body->length == 1); { fprintf(stderr,"Body length error\n"); return -1 ; } /* don't send that one character, because its part of the trailer. */ trailer->hash=hash; CB(cbinfo,OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER,&content2); return total; }
int main(int argc,char **argv) { const char *keyfile; const char *plainfile; const char *user_id; const char *hashstr; const char *sigfile; ops_secret_key_t *skey; ops_create_signature_t *sig; ops_hash_algorithm_t alg; int fd; ops_create_info_t *info; unsigned char keyid[OPS_KEY_ID_SIZE]; if(argc != 6) { fprintf(stderr,"%s <secret key file> <user_id> <hash> <plaintext file>" " <signature file>\n",argv[0]); exit(1); } keyfile=argv[1]; user_id=argv[2]; hashstr=argv[3]; plainfile=argv[4]; sigfile=argv[5]; ops_init(); skey=get_secret_key(keyfile); assert(skey); alg=ops_hash_algorithm_from_text(hashstr); if(alg == OPS_HASH_UNKNOWN) { fprintf(stderr,"Unkonwn hash algorithm: %s\n",hashstr); exit(2); } sig=ops_create_signature_new(); ops_signature_start_cleartext_signature(sig,skey,alg,OPS_SIG_BINARY); fd=open(plainfile,O_RDONLY); if(fd < 0) { perror(plainfile); exit(3); } for( ; ; ) { unsigned char buf[8192]; int n; n=read(fd,buf,sizeof buf); if(!n) break; if(n < 0) { perror(plainfile); exit(4); } ops_signature_add_data(sig,buf,n); } close(fd); ops_signature_add_creation_time(sig,time(NULL)); ops_keyid(keyid,&skey->public_key); ops_signature_add_issuer_key_id(sig,keyid); ops_signature_hashed_subpackets_end(sig); fd=open(sigfile,O_CREAT|O_TRUNC|O_WRONLY,0666); if(fd < 0) { perror(sigfile); exit(5); } info=ops_create_info_new(); ops_writer_set_fd(info,fd); ops_write_signature(sig,&skey->public_key,skey,info); ops_secret_key_free(skey); return 0; }